From 578d2c74b5ed945c5599065509570a7ede93f71b Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Thu, 24 Sep 2026 15:07:32 +0200 Subject: [PATCH 01/25] Add agent-binary as workspace member --- Cargo.lock | 12 +++++ Cargo.nix | 70 +++++++++++++++++++++----- Cargo.toml | 2 +- rust/agent-binary/Cargo.toml | 24 +++++++++ rust/agent-binary/build.rs | 3 ++ rust/agent-binary/src/framework/mod.rs | 12 +++++ rust/agent-binary/src/main.rs | 47 +++++++++++++++++ 7 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 rust/agent-binary/Cargo.toml create mode 100644 rust/agent-binary/build.rs create mode 100644 rust/agent-binary/src/framework/mod.rs create mode 100644 rust/agent-binary/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 75704686b..b08d28809 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3173,6 +3173,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "stackable-kafka-agent" +version = "0.0.0-dev" +dependencies = [ + "anyhow", + "built", + "clap", + "stackable-operator", + "tokio", + "tracing", +] + [[package]] name = "stackable-kafka-operator" version = "0.0.0-dev" diff --git a/Cargo.nix b/Cargo.nix index 1b1ba51b5..292f308c7 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -38,23 +38,21 @@ rec { # "public" attributes that we attempt to keep stable with new versions of crate2nix. # - rootCrate = rec { - packageId = "stackable-kafka-operator"; - # Use this attribute to refer to the derivation building your root crate package. - # You can override the features with rootCrate.build.override { features = [ "default" "feature1" ... ]; }. - build = internal.buildRustCrateWithFeatures { - inherit packageId; - }; - - # Debug support which might change between releases. - # File a bug if you depend on any for non-debug work! - debug = internal.debugCrate { inherit packageId; }; - }; # Refer your crate build derivation by name here. # You can override the features with # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. workspaceMembers = { + "stackable-kafka-agent" = rec { + packageId = "stackable-kafka-agent"; + build = internal.buildRustCrateWithFeatures { + packageId = "stackable-kafka-agent"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; "stackable-kafka-operator" = rec { packageId = "stackable-kafka-operator"; build = internal.buildRustCrateWithFeatures { @@ -10423,6 +10421,54 @@ rec { }; resolvedDefaultFeatures = [ "default" "rustls" ]; }; + "stackable-kafka-agent" = rec { + crateName = "stackable-kafka-agent"; + version = "0.0.0-dev"; + edition = "2024"; + crateBin = [ + { + name = "stackable-kafka-agent"; + path = "src/main.rs"; + requiredFeatures = [ ]; + } + ]; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./rust/agent-binary; }; + authors = [ + "Stackable GmbH " + ]; + dependencies = [ + { + name = "anyhow"; + packageId = "anyhow"; + } + { + name = "clap"; + packageId = "clap"; + } + { + name = "stackable-operator"; + packageId = "stackable-operator"; + features = [ "crds" "webhook" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + buildDependencies = [ + { + name = "built"; + packageId = "built"; + features = [ "chrono" "git2" ]; + } + ]; + + }; "stackable-kafka-operator" = rec { crateName = "stackable-kafka-operator"; version = "0.0.0-dev"; diff --git a/Cargo.toml b/Cargo.toml index 2eac6bf58..5e9c33132 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["rust/operator-binary"] +members = ["rust/operator-binary", "rust/agent-binary"] resolver = "2" [workspace.package] diff --git a/rust/agent-binary/Cargo.toml b/rust/agent-binary/Cargo.toml new file mode 100644 index 000000000..c138e675b --- /dev/null +++ b/rust/agent-binary/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "stackable-kafka-agent" +description = "Stackable Agent for Apache Kafka" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +publish = false + +[dependencies] +stackable-operator.workspace = true + +anyhow.workspace = true +clap.workspace = true +tokio.workspace = true +tracing.workspace = true + +[build-dependencies] +built.workspace = true + +[[bin]] +name = "stackable-kafka-agent" +path = "src/main.rs" diff --git a/rust/agent-binary/build.rs b/rust/agent-binary/build.rs new file mode 100644 index 000000000..fa809bfd1 --- /dev/null +++ b/rust/agent-binary/build.rs @@ -0,0 +1,3 @@ +fn main() { + built::write_built_file().unwrap(); +} diff --git a/rust/agent-binary/src/framework/mod.rs b/rust/agent-binary/src/framework/mod.rs new file mode 100644 index 000000000..c26b5e711 --- /dev/null +++ b/rust/agent-binary/src/framework/mod.rs @@ -0,0 +1,12 @@ +//! Reusable, product-agnostic agent building blocks. Staged here until they move to operator-rs. + +use clap::Args; +use stackable_operator::cli::CommonOptions; + +/// Agent subcommands. Like [`stackable_operator::cli::Command`], but without `crd` as CRDs are only +/// deployed by operators. +#[derive(Debug, clap::Parser)] +pub enum AgentCommand { + /// Run the agent. + Run(Run), +} diff --git a/rust/agent-binary/src/main.rs b/rust/agent-binary/src/main.rs new file mode 100644 index 000000000..64e2cad91 --- /dev/null +++ b/rust/agent-binary/src/main.rs @@ -0,0 +1,47 @@ +//! The Stackable Kafka agent: a per-cluster controller that reconciles in-cluster resources like `KafkaTopic`s. + +use clap::Parser; +use stackable_operator::{ + cli::CommonOptions, + telemetry::Tracing, + utils::signal::SignalWatcher, +}; + +use crate::framework::AgentCommand; + +mod framework; + +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); +} + +#[derive(clap::Parser)] +#[clap(about, author)] +struct Opts { + #[clap(subcommand)] + cmd: AgentCommand, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + match Opts::parse().cmd { + AgentCommand::Run(CommonOptions { telemetry, .. }) => { + let _tracing_guard = Tracing::pre_configured(built_info::PKG_NAME, telemetry).init()?; + + tracing::info!( + built_info.pkg_version = built_info::PKG_VERSION, + built_info.git_version = built_info::GIT_VERSION, + built_info.target = built_info::TARGET, + built_info.built_time_utc = built_info::BUILT_TIME_UTC, + built_info.rustc_version = built_info::RUSTC_VERSION, + "Starting {description}", + description = built_info::PKG_DESCRIPTION + ); + + let sigterm_watcher = SignalWatcher::sigterm()?; + sigterm_watcher.handle().await; + } + } + + Ok(()) +} From 2a1fae09ec06ce67308b1fccdad5350d96f4d23a Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Thu, 24 Sep 2026 16:03:50 +0200 Subject: [PATCH 02/25] deploy the agent if spec.platformAcces.enabled is configured --- extra/crds.yaml | 41 +++ rust/agent-binary/src/main.rs | 6 +- rust/operator-binary/src/controller.rs | 28 +- rust/operator-binary/src/controller/apply.rs | 3 + .../src/controller/build/mod.rs | 34 +- .../src/controller/build/resource/agent.rs | 303 ++++++++++++++++++ .../src/controller/build/resource/mod.rs | 1 + .../src/controller/validate.rs | 16 +- rust/operator-binary/src/crd/mod.rs | 44 ++- .../src/framework/commons/mod.rs | 1 + .../framework/commons/platform_access/mod.rs | 3 + .../framework/commons/platform_access/tls.rs | 87 +++++ .../src/framework/constants/mod.rs | 1 + .../src/framework/constants/secret.rs | 2 + .../src/framework/kvp/label.rs | 45 +++ rust/operator-binary/src/framework/kvp/mod.rs | 1 + rust/operator-binary/src/framework/mod.rs | 6 + rust/operator-binary/src/main.rs | 18 +- 18 files changed, 619 insertions(+), 21 deletions(-) create mode 100644 rust/operator-binary/src/controller/build/resource/agent.rs create mode 100644 rust/operator-binary/src/framework/commons/mod.rs create mode 100644 rust/operator-binary/src/framework/commons/platform_access/mod.rs create mode 100644 rust/operator-binary/src/framework/commons/platform_access/tls.rs create mode 100644 rust/operator-binary/src/framework/constants/mod.rs create mode 100644 rust/operator-binary/src/framework/constants/secret.rs create mode 100644 rust/operator-binary/src/framework/kvp/label.rs create mode 100644 rust/operator-binary/src/framework/kvp/mod.rs create mode 100644 rust/operator-binary/src/framework/mod.rs diff --git a/extra/crds.yaml b/extra/crds.yaml index 9283cc4ff..7c5f5161f 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -2136,6 +2136,47 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + platformAccess: + description: Access of the Stackable Data Platform to this cluster. + nullable: true + properties: + authentication: + description: The credential the agent authenticates to Kafka with. + oneOf: + - required: + - tls + properties: + tls: + description: 'Source of a TLS client certificate: a secret-operator SecretClass or a static Secret.' + oneOf: + - required: + - secretClass + - required: + - secret + properties: + secret: + description: |- + A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), such as a + Secret of type `kubernetes.io/tls`. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + secretClass: + description: An AutoTLS SecretClass used to provision the certificate. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: object + type: object + enabled: + default: false + description: Whether the operator deploys the agent. False by default. + type: boolean + required: + - authentication + type: object required: - brokers - image diff --git a/rust/agent-binary/src/main.rs b/rust/agent-binary/src/main.rs index 64e2cad91..6ab5c58f7 100644 --- a/rust/agent-binary/src/main.rs +++ b/rust/agent-binary/src/main.rs @@ -1,11 +1,7 @@ //! The Stackable Kafka agent: a per-cluster controller that reconciles in-cluster resources like `KafkaTopic`s. use clap::Parser; -use stackable_operator::{ - cli::CommonOptions, - telemetry::Tracing, - utils::signal::SignalWatcher, -}; +use stackable_operator::{cli::CommonOptions, telemetry::Tracing, utils::signal::SignalWatcher}; use crate::framework::AgentCommand; diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 21e1d8de4..1dc977ea1 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -22,7 +22,7 @@ use stackable_operator::{ constant, crd::listener, k8s_openapi::api::{ - apps::v1::StatefulSet, + apps::v1::{Deployment, StatefulSet}, core::v1::{ConfigMap, Service, ServiceAccount}, policy::v1::PodDisruptionBudget, rbac::v1::RoleBinding, @@ -65,7 +65,8 @@ use crate::{ update_status::update_status, }, crd::{ - APP_NAME, KAFKA_OPERATOR_NAME, KafkaPodDescriptor, MetadataManager, + APP_NAME, KAFKA_OPERATOR_NAME, KafkaPlatformAccessAuthentication, KafkaPodDescriptor, + MetadataManager, authorization::KafkaAuthorizationConfig, role::{AnyConfig, AnyConfigOverrides, KafkaRole}, v1alpha1, @@ -112,6 +113,7 @@ pub struct Applied; /// bootstrap [`Listener`](listener)s. pub struct KubernetesResources { pub stateful_sets: Vec, + pub deployments: Vec, pub services: Vec, pub listeners: Vec, pub config_maps: Vec, @@ -151,6 +153,7 @@ pub struct ValidatedCluster { /// address-less around the first reconcile runs; the listener-operator populates the ingress /// addresses and the `Listener` watch triggers a new run once it does. pub bootstrap_listeners: Vec, + pub agent_config: Option, } impl ValidatedCluster { @@ -165,6 +168,7 @@ impl ValidatedCluster { role_configs: BTreeMap, role_group_configs: BTreeMap>, bootstrap_listeners: Vec, + agent_config: Option, ) -> Self { // `app_version_label_value` is constructed to be a valid label value, so it is also a // valid `ProductVersion`. @@ -187,6 +191,7 @@ impl ValidatedCluster { role_configs, role_group_configs, bootstrap_listeners, + agent_config, } } @@ -339,6 +344,12 @@ impl ValidatedClusterConfig { } } +/// The configuration of the agent deployed with the cluster. +pub struct ValidatedAgentConfig { + pub image: String, + pub authentication: KafkaPlatformAccessAuthentication, +} + /// Per-role configuration extracted during validation. /// /// Resolved from the raw [`v1alpha1::KafkaCluster`] spec during validation so the reconcile loop @@ -397,6 +408,7 @@ pub type ValidatedRoleGroupConfig = stackable_operator::v2::role_utils::RoleGrou pub struct Ctx { pub client: stackable_operator::client::Client, pub operator_environment: OperatorEnvironmentOptions, + pub agent_image: String, } #[derive(Snafu, Debug, EnumDiscriminants)] @@ -466,9 +478,13 @@ pub async fn reconcile_kafka( .context(DereferenceSnafu)?; // validate (no client required) - let validated_cluster = - validate::validate(kafka, dereferenced_objects, &ctx.operator_environment) - .context(ValidateClusterSnafu)?; + let validated_cluster = validate::validate( + kafka, + dereferenced_objects, + &ctx.operator_environment, + &ctx.agent_image, + ) + .context(ValidateClusterSnafu)?; tracing::debug!( kerberos_enabled = validated_cluster.cluster_config.kafka_security.has_kerberos_enabled(), @@ -628,6 +644,7 @@ pub(crate) mod test_support { bootstrap_listeners: Vec::new(), }, &operator_environment(), + &crate::crd::default_agent_image(&operator_environment().image_repository), ) } } @@ -780,6 +797,7 @@ spec: {} operator_service_name: "kafka-operator".to_owned(), image_repository: "oci.stackable.tech/sdp".to_owned(), }, + agent_image: crate::crd::default_agent_image("oci.stackable.tech/sdp"), }); reconcile_kafka(Arc::new(kafka), ctx).await diff --git a/rust/operator-binary/src/controller/apply.rs b/rust/operator-binary/src/controller/apply.rs index 1ce080f87..5f740ecc4 100644 --- a/rust/operator-binary/src/controller/apply.rs +++ b/rust/operator-binary/src/controller/apply.rs @@ -78,6 +78,7 @@ impl<'a> Applier<'a> { // compile here instead of silently never being applied. let KubernetesResources { stateful_sets, + deployments, services, listeners, config_maps, @@ -97,6 +98,7 @@ impl<'a> Applier<'a> { let config_maps = self.add_resources(config_maps).await?; let pod_disruption_budgets = self.add_resources(pod_disruption_budgets).await?; let stateful_sets = self.add_resources(stateful_sets).await?; + let deployments = self.add_resources(deployments).await?; self.cluster_resources .delete_orphaned_resources(self.client) @@ -105,6 +107,7 @@ impl<'a> Applier<'a> { Ok(KubernetesResources { stateful_sets, + deployments, services, listeners, config_maps, diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index 1be5313e1..2283c4448 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -14,6 +14,9 @@ use crate::{ listener::get_kafka_listener_config, product_logging::vector_config_file_content, }, resource::{ + agent::{ + build_agent_deployment, build_agent_role_binding, build_agent_service_account, + }, config_map::build_rolegroup_config_map, discovery::build_discovery_configmap, listener::build_broker_rolegroup_bootstrap_listener, @@ -27,6 +30,7 @@ use crate::{ }, }, crd::role::{AnyConfig, KafkaRole}, + framework::kvp::label as framework_label, }; pub mod command; @@ -149,14 +153,24 @@ pub fn build(cluster: &ValidatedCluster) -> Result config_maps.push(build_discovery_configmap(cluster).context(DiscoveryConfigMapSnafu)?); + let mut deployments = vec![]; + let mut service_accounts = vec![build_service_account(cluster)]; + let mut role_bindings = vec![build_role_binding(cluster)]; + if let Some(agent_config) = &cluster.agent_config { + deployments.push(build_agent_deployment(cluster, agent_config)); + service_accounts.push(build_agent_service_account(cluster)); + role_bindings.push(build_agent_role_binding(cluster)); + } + Ok(KubernetesResources { stateful_sets, + deployments, services, listeners, config_maps, pod_disruption_budgets, - service_accounts: vec![build_service_account(cluster)], - role_bindings: vec![build_role_binding(cluster)], + service_accounts, + role_bindings, status: PhantomData, }) } @@ -171,6 +185,16 @@ pub(crate) fn recommended_labels_for_cluster_resources(cluster: &ValidatedCluste ) } +pub(crate) fn recommended_labels_for_agent_resources(cluster: &ValidatedCluster) -> Labels { + framework_label::recommended_labels_for_agent_resources( + &cluster.name, + &PRODUCT_NAME, + &cluster.product_version, + &OPERATOR_NAME, + &CONTROLLER_NAME, + ) +} + pub(crate) fn recommended_labels_for_role_resources( cluster: &ValidatedCluster, role_name: &RoleName, @@ -217,6 +241,10 @@ pub(crate) fn recommended_labels_for_unversioned_role_group_resources( } /// Selector labels matching the pods of a role group. +pub(crate) fn agent_selector(cluster: &ValidatedCluster) -> Labels { + framework_label::agent_selector(&cluster.name, &PRODUCT_NAME) +} + pub(crate) fn role_group_selector( cluster: &ValidatedCluster, role_name: &RoleName, @@ -363,6 +391,8 @@ mod tests { sorted_names(&resources.role_bindings), ["simple-kafka-rolebinding"] ); + // No agent without platform access. + assert!(resources.deployments.is_empty()); } #[test] diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs new file mode 100644 index 000000000..e466512fd --- /dev/null +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -0,0 +1,303 @@ +//! Builds the resources of the platform-access agent deployed alongside the cluster. + +use std::str::FromStr; + +use stackable_operator::{ + builder::{ + meta::ObjectMetaBuilder, + pod::{ + PodBuilder, resources::ResourceRequirementsBuilder, security::PodSecurityContextBuilder, + }, + }, + constant, + k8s_openapi::{ + api::{ + apps::v1::{Deployment, DeploymentSpec}, + core::v1::{EnvVarSource, ObjectFieldSelector, ServiceAccount}, + rbac::v1::{RoleBinding, RoleRef, Subject}, + }, + apimachinery::pkg::apis::meta::v1::LabelSelector, + }, + kube::api::ObjectMeta, + v2::{ + builder::{meta::ownerreference_from_resource, pod::container::new_container_builder}, + types::kubernetes::ContainerName, + }, +}; + +use crate::{ + controller::{ + ValidatedAgentConfig, ValidatedCluster, + build::{agent_selector, recommended_labels_for_agent_resources}, + }, + crd::KafkaPlatformAccessAuthentication, +}; + +constant!(AGENT_CONTAINER_NAME: ContainerName = "agent"); +pub const AGENT_CLUSTER_ROLE_NAME: &str = "kafka-agent-clusterrole"; + +pub fn build_agent_deployment( + cluster: &ValidatedCluster, + agent_config: &ValidatedAgentConfig, +) -> Deployment { + let mut cb_agent = new_container_builder(&AGENT_CONTAINER_NAME); + let mut pod_builder = PodBuilder::new(); + + match &agent_config.authentication { + KafkaPlatformAccessAuthentication::Tls(credential) => { + credential.add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) + } + } + + cb_agent + .image(&agent_config.image) + .args(vec!["run".to_owned()]) + .add_env_var_from_source( + "KUBERNETES_NODE_NAME", + EnvVarSource { + field_ref: Some(ObjectFieldSelector { + field_path: "spec.nodeName".to_owned(), + ..ObjectFieldSelector::default() + }), + ..EnvVarSource::default() + }, + ) + // Saves the agent from looking the domain up via the kubelet, which needs extra RBAC. + .add_env_var( + "KUBERNETES_CLUSTER_DOMAIN", + cluster.cluster_domain.to_string(), + ) + .resources( + ResourceRequirementsBuilder::new() + .with_cpu_request("100m") + .with_cpu_limit("500m") + .with_memory_request("128Mi") + .with_memory_limit("128Mi") + .build(), + ); + + pod_builder + .metadata( + ObjectMetaBuilder::new() + .with_labels(recommended_labels_for_agent_resources(cluster)) + .build(), + ) + .add_container(cb_agent.build()) + .service_account_name(agent_name(cluster)) + .security_context(PodSecurityContextBuilder::with_stackable_defaults().build()); + + Deployment { + metadata: agent_metadata(cluster), + spec: Some(DeploymentSpec { + replicas: Some(1), + selector: LabelSelector { + match_labels: Some(agent_selector(cluster).into()), + ..LabelSelector::default() + }, + template: pod_builder.build_template(), + ..DeploymentSpec::default() + }), + status: None, + } +} + +pub fn build_agent_service_account(cluster: &ValidatedCluster) -> ServiceAccount { + ServiceAccount { + metadata: agent_metadata(cluster), + ..ServiceAccount::default() + } +} + +/// Binds the agent ServiceAccount to the agent ClusterRole deployed by the Helm chart. +pub fn build_agent_role_binding(cluster: &ValidatedCluster) -> RoleBinding { + RoleBinding { + metadata: agent_metadata(cluster), + role_ref: RoleRef { + api_group: Some("rbac.authorization.k8s.io".to_owned()), + kind: "ClusterRole".to_owned(), + name: AGENT_CLUSTER_ROLE_NAME.to_owned(), + }, + subjects: Some(vec![Subject { + kind: "ServiceAccount".to_owned(), + name: agent_name(cluster), + namespace: Some(cluster.namespace.to_string()), + ..Subject::default() + }]), + } +} + +/// The name of all agent resources. Kinds don't share a namespace, so unlike a suffix per kind, this +/// cannot collide with the resources of a cluster named `-agent`. +fn agent_name(cluster: &ValidatedCluster) -> String { + format!("{}-agent", cluster.name) +} + +fn agent_metadata(cluster: &ValidatedCluster) -> ObjectMeta { + ObjectMetaBuilder::new() + .name_and_namespace(cluster) + .name(agent_name(cluster)) + .ownerreference(ownerreference_from_resource(cluster, None, Some(true))) + .with_labels(recommended_labels_for_agent_resources(cluster)) + .build() +} + +#[cfg(test)] +mod tests { + use serde_json::{Value, json}; + + use super::*; + use crate::{ + controller::test_support::{app_version_label, minimal_kafka, validated_cluster}, + crd::default_agent_image, + }; + + fn cluster(platform_access: &str) -> ValidatedCluster { + let kafka = minimal_kafka(&format!( + r#" + apiVersion: kafka.stackable.tech/v1alpha1 + kind: KafkaCluster + metadata: + name: simple-kafka + namespace: default + uid: 12345678-1234-1234-1234-123456789012 + spec: + image: + productVersion: 3.9.2 + clusterConfig: + zookeeperConfigMapName: xyz + platformAccess: {platform_access} + brokers: + roleGroups: + default: + replicas: 1 + "# + )); + validated_cluster(&kafka) + } + + fn agent_deployment(platform_access: &str) -> Value { + let cluster = cluster(platform_access); + let agent_config = cluster + .agent_config + .as_ref() + .expect("platform access is enabled"); + serde_json::to_value(build_agent_deployment(&cluster, agent_config)) + .expect("must be serializable") + } + + #[test] + fn agent_config_is_only_resolved_if_platform_access_is_enabled() { + assert!( + cluster("{enabled: false, authentication: {tls: {secretClass: tls}}}") + .agent_config + .is_none() + ); + + let cluster = cluster("{enabled: true, authentication: {tls: {secretClass: tls}}}"); + let agent_config = cluster.agent_config.expect("platform access is enabled"); + assert_eq!(agent_config.image, default_agent_image("oci.example.org")); + } + + #[test] + fn test_deployment() { + let deployment = + agent_deployment("{enabled: true, authentication: {tls: {secretClass: tls}}}"); + + assert_eq!(deployment["metadata"]["name"], "simple-kafka-agent"); + assert_eq!(deployment["spec"]["replicas"], 1); + // The selector must not match the broker or controller Pods. + assert_eq!( + deployment["spec"]["selector"]["matchLabels"], + json!({ + "app.kubernetes.io/component": "agent", + "app.kubernetes.io/instance": "simple-kafka", + "app.kubernetes.io/name": "kafka" + }) + ); + assert_eq!( + deployment["spec"]["template"]["metadata"]["labels"], + json!({ + "app.kubernetes.io/component": "agent", + "app.kubernetes.io/instance": "simple-kafka", + "app.kubernetes.io/managed-by": "kafka.stackable.tech_kafkacluster", + "app.kubernetes.io/name": "kafka", + "app.kubernetes.io/version": app_version_label("3.9.2"), + "stackable.tech/vendor": "Stackable" + }) + ); + + let pod_spec = &deployment["spec"]["template"]["spec"]; + assert_eq!(pod_spec["serviceAccountName"], "simple-kafka-agent"); + assert_eq!( + pod_spec["containers"][0]["image"], + default_agent_image("oci.example.org") + ); + assert_eq!(pod_spec["containers"][0]["args"], json!(["run"])); + assert_eq!( + pod_spec["containers"][0]["volumeMounts"], + json!([{"mountPath": "/stackable/secrets/tls-tls-cert", "name": "tls-tls-cert"}]) + ); + assert_eq!(pod_spec["volumes"][0]["name"], "tls-tls-cert"); + assert_eq!( + pod_spec["volumes"][0]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"]["secrets.stackable.tech/class"], + "tls" + ); + } + + #[test] + fn test_deployment_with_static_secret() { + let deployment = + agent_deployment("{enabled: true, authentication: {tls: {secret: my-cert}}}"); + + assert_eq!( + deployment["spec"]["template"]["spec"]["volumes"], + json!([{"name": "my-cert-tls-cert", "secret": {"secretName": "my-cert"}}]) + ); + } + + #[test] + fn test_role_binding() { + let cluster = cluster("{enabled: true, authentication: {tls: {secretClass: tls}}}"); + + assert_eq!( + json!({ + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "RoleBinding", + "metadata": { + "labels": { + "app.kubernetes.io/component": "agent", + "app.kubernetes.io/instance": "simple-kafka", + "app.kubernetes.io/managed-by": "kafka.stackable.tech_kafkacluster", + "app.kubernetes.io/name": "kafka", + "app.kubernetes.io/version": app_version_label("3.9.2"), + "stackable.tech/vendor": "Stackable" + }, + "name": "simple-kafka-agent", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "kafka.stackable.tech/v1alpha1", + "controller": true, + "kind": "KafkaCluster", + "name": "simple-kafka", + "uid": "12345678-1234-1234-1234-123456789012" + } + ] + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "kafka-agent-clusterrole" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "simple-kafka-agent", + "namespace": "default" + } + ] + }), + serde_json::to_value(build_agent_role_binding(&cluster)).expect("must be serializable") + ); + } +} diff --git a/rust/operator-binary/src/controller/build/resource/mod.rs b/rust/operator-binary/src/controller/build/resource/mod.rs index 7f458714f..4acba6265 100644 --- a/rust/operator-binary/src/controller/build/resource/mod.rs +++ b/rust/operator-binary/src/controller/build/resource/mod.rs @@ -1,5 +1,6 @@ //! Builders that assemble Kubernetes resources for kafka rolegroups. +pub mod agent; pub mod config_map; pub mod discovery; pub mod listener; diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index a10c879f6..cc562eeee 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -30,8 +30,8 @@ use stackable_operator::{ use crate::{ controller::{ - RoleGroupName, ValidatedCluster, ValidatedClusterConfig, ValidatedKafkaConfig, - ValidatedRoleConfig, ValidatedRoleGroupConfig, + RoleGroupName, ValidatedAgentConfig, ValidatedCluster, ValidatedClusterConfig, + ValidatedKafkaConfig, ValidatedRoleConfig, ValidatedRoleGroupConfig, dereference::DereferencedObjects, security::{self, ValidatedKafkaSecurity}, }, @@ -199,6 +199,7 @@ pub fn validate( kafka: &v1alpha1::KafkaCluster, dereferenced_objects: DereferencedObjects, operator_environment: &OperatorEnvironmentOptions, + agent_image: &str, ) -> Result { let image = kafka .spec @@ -333,6 +334,16 @@ pub fn validate( .cluster_domain .clone(); + let agent_config = kafka + .spec + .platform_access + .as_ref() + .filter(|platform_access| platform_access.enabled) + .map(|platform_access| ValidatedAgentConfig { + image: agent_image.to_owned(), + authentication: platform_access.authentication.clone(), + }); + Ok(ValidatedCluster::new( name, namespace, @@ -353,6 +364,7 @@ pub fn validate( role_configs, role_group_configs, dereferenced_objects.bootstrap_listeners, + agent_config, )) } diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 3402151fa..34081db27 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -38,13 +38,25 @@ use stackable_operator::{ }; use strum::{Display, EnumIter, EnumString}; -use crate::crd::{ - authorization::KafkaAuthorization, - role::{KafkaRole, broker::BrokerConfigFragment, controller::ControllerConfigFragment}, - tls::KafkaTls, +use crate::{ + crd::{ + authorization::KafkaAuthorization, + role::{KafkaRole, broker::BrokerConfigFragment, controller::ControllerConfigFragment}, + tls::KafkaTls, + }, + framework::commons::platform_access::tls::TlsClientCredential, }; pub const CONTAINER_IMAGE_BASE_NAME: &str = "kafka"; +pub const AGENT_IMAGE_BASE_NAME: &str = "kafka-agent"; + +/// The agent image of the same release as the operator. +pub fn default_agent_image(image_repository: &str) -> String { + format!( + "{image_repository}/{AGENT_IMAGE_BASE_NAME}:{}", + crate::built_info::PKG_VERSION + ) +} pub const APP_NAME: &str = "kafka"; pub const KAFKA_OPERATOR_NAME: &str = "kafka.stackable.tech"; pub const FIELD_MANAGER: &str = "kafka-operator"; @@ -98,6 +110,26 @@ pub type ControllerRole = Role< JavaCommonConfig, >; +/// Access of the Stackable Data Platform to this Kafka cluster, used by an agent to manage resources +/// like `KafkaTopic`s. The credential must be authorized in Kafka by the user. +#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct KafkaPlatformAccess { + /// Whether the operator deploys the agent. False by default. + #[serde(default)] + pub enabled: bool, + + /// The credential the agent authenticates to Kafka with. + pub authentication: KafkaPlatformAccessAuthentication, +} + +/// How the agent authenticates to Kafka. +#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum KafkaPlatformAccessAuthentication { + Tls(TlsClientCredential), +} + #[versioned( version(name = "v1alpha1"), crates( @@ -138,6 +170,10 @@ pub mod versioned { #[serde(default)] pub cluster_config: v1alpha1::KafkaClusterConfig, + /// Access of the Stackable Data Platform to this cluster. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub platform_access: Option, + // no doc - docs in ClusterOperation struct. #[serde(default)] pub cluster_operation: ClusterOperation, diff --git a/rust/operator-binary/src/framework/commons/mod.rs b/rust/operator-binary/src/framework/commons/mod.rs new file mode 100644 index 000000000..ad8d7e6bd --- /dev/null +++ b/rust/operator-binary/src/framework/commons/mod.rs @@ -0,0 +1 @@ +pub mod platform_access; diff --git a/rust/operator-binary/src/framework/commons/platform_access/mod.rs b/rust/operator-binary/src/framework/commons/platform_access/mod.rs new file mode 100644 index 000000000..7cedc76bf --- /dev/null +++ b/rust/operator-binary/src/framework/commons/platform_access/mod.rs @@ -0,0 +1,3 @@ +//! Credentials a product cluster grants the platform-access agent, and how to mount them. + +pub mod tls; diff --git a/rust/operator-binary/src/framework/commons/platform_access/tls.rs b/rust/operator-binary/src/framework/commons/platform_access/tls.rs new file mode 100644 index 000000000..592d1e51b --- /dev/null +++ b/rust/operator-binary/src/framework/commons/platform_access/tls.rs @@ -0,0 +1,87 @@ +use serde::{Deserialize, Serialize}; +use stackable_operator::{ + builder::pod::{ + PodBuilder, + container::ContainerBuilder, + volume::{ + SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder, VolumeMountBuilder, + }, + }, + commons::secret_class::SecretClassVolumeProvisionParts, + k8s_openapi::api::core::v1::{SecretVolumeSource, Volume, VolumeMount}, + schemars::{self, JsonSchema}, + v2::types::kubernetes::{SecretClassName, SecretName}, +}; + +use crate::framework::constants::secret::SECRET_BASE_PATH; + +/// Source of a TLS client certificate: a secret-operator SecretClass or a static Secret. +#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum TlsClientCredential { + /// An AutoTLS SecretClass used to provision the certificate. + SecretClass(SecretClassName), + + /// A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), such as a + /// Secret of type `kubernetes.io/tls`. + Secret(SecretName), +} + +impl TlsClientCredential { + /// Adds the certificate volume to the Pod and mounts it into all given containers. + pub fn add_volumes_and_mounts( + &self, + pod_builder: &mut PodBuilder, + container_builders: Vec<&mut ContainerBuilder>, + ) { + let (volumes, mounts) = self.volumes_and_mounts(); + pod_builder + .add_volumes(volumes) + .expect("The volume name is derived from the credential and should not collide."); + for container_builder in container_builders { + container_builder + .add_volume_mounts(mounts.clone()) + .expect("The mount path is derived from the credential and should not collide."); + } + } + + fn volumes_and_mounts(&self) -> (Vec, Vec) { + let volume_name = self.volume_name(); + let volume = match self { + Self::SecretClass(secret_class) => VolumeBuilder::new(&volume_name) + .ephemeral( + SecretOperatorVolumeSourceBuilder::new( + secret_class, + SecretClassVolumeProvisionParts::PublicPrivate, + ) + .with_pod_scope() + .with_format(SecretFormat::TlsPem) + .build() + .expect("the annotations are built from a valid SecretClass name"), + ) + .build(), + Self::Secret(secret) => Volume { + name: volume_name.clone(), + secret: Some(SecretVolumeSource { + secret_name: Some(secret.to_string()), + ..SecretVolumeSource::default() + }), + ..Volume::default() + }, + }; + let mount = VolumeMountBuilder::new(&volume_name, self.mount_path()).build(); + (vec![volume], vec![mount]) + } + + /// The directory containing `tls.crt`, `tls.key` and `ca.crt` (PEM). + pub fn mount_path(&self) -> String { + format!("{SECRET_BASE_PATH}/{}", self.volume_name()) + } + + fn volume_name(&self) -> String { + match self { + Self::SecretClass(secret_class) => format!("{secret_class}-tls-cert"), + Self::Secret(secret) => format!("{secret}-tls-cert"), + } + } +} diff --git a/rust/operator-binary/src/framework/constants/mod.rs b/rust/operator-binary/src/framework/constants/mod.rs new file mode 100644 index 000000000..73b12dbbd --- /dev/null +++ b/rust/operator-binary/src/framework/constants/mod.rs @@ -0,0 +1 @@ +pub mod secret; diff --git a/rust/operator-binary/src/framework/constants/secret.rs b/rust/operator-binary/src/framework/constants/secret.rs new file mode 100644 index 000000000..320faf979 --- /dev/null +++ b/rust/operator-binary/src/framework/constants/secret.rs @@ -0,0 +1,2 @@ +// Mirrors the crate-private `SECRET_BASE_PATH` of operator-rs. +pub(crate) const SECRET_BASE_PATH: &str = "/stackable/secrets"; diff --git a/rust/operator-binary/src/framework/kvp/label.rs b/rust/operator-binary/src/framework/kvp/label.rs new file mode 100644 index 000000000..f3695b8c7 --- /dev/null +++ b/rust/operator-binary/src/framework/kvp/label.rs @@ -0,0 +1,45 @@ +use stackable_operator::{ + kvp::{Label, Labels}, + v2::{ + kvp::label::{ + label_app_kubernetes_io_instance, label_app_kubernetes_io_managed_by, + label_app_kubernetes_io_name, label_app_kubernetes_io_version, + label_stackable_tech_vendor, + }, + types::operator::{ClusterName, ControllerName, OperatorName, ProductName, ProductVersion}, + }, +}; + +/// Creates the recommended labels for agent resources, like the agent Deployment. +pub fn recommended_labels_for_agent_resources( + cluster_name: &ClusterName, + product_name: &ProductName, + product_version: &ProductVersion, + operator_name: &OperatorName, + controller_name: &ControllerName, +) -> Labels { + Labels::from_iter([ + label_app_kubernetes_io_instance(cluster_name), + label_app_kubernetes_io_name(product_name), + label_app_kubernetes_io_version(product_version), + label_app_kubernetes_io_component_agent(), + label_app_kubernetes_io_managed_by(operator_name, controller_name), + label_stackable_tech_vendor(), + ]) +} + +/// Creates the agent selector. +/// +/// The returned labels are a subset of the recommended labels for agent resources. +pub fn agent_selector(cluster_name: &ClusterName, product_name: &ProductName) -> Labels { + Labels::from_iter([ + label_app_kubernetes_io_instance(cluster_name), + label_app_kubernetes_io_name(product_name), + label_app_kubernetes_io_component_agent(), + ]) +} + +/// Creates the `app.kubernetes.io/component` label with the value `agent`. +pub fn label_app_kubernetes_io_component_agent() -> Label { + Label::component("agent").expect("\"agent\" is a valid label value") +} diff --git a/rust/operator-binary/src/framework/kvp/mod.rs b/rust/operator-binary/src/framework/kvp/mod.rs new file mode 100644 index 000000000..0006163a0 --- /dev/null +++ b/rust/operator-binary/src/framework/kvp/mod.rs @@ -0,0 +1 @@ +pub mod label; diff --git a/rust/operator-binary/src/framework/mod.rs b/rust/operator-binary/src/framework/mod.rs new file mode 100644 index 000000000..842c16dde --- /dev/null +++ b/rust/operator-binary/src/framework/mod.rs @@ -0,0 +1,6 @@ +//! Product-agnostic building blocks, staged here until they move to operator-rs. The module paths +//! mirror operator-rs, so moving code there only changes imports. + +pub mod commons; +pub mod constants; +pub mod kvp; diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 075b48e11..941f4aa1e 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -14,7 +14,7 @@ use stackable_operator::{ crd::listener, eos::EndOfSupportChecker, k8s_openapi::api::{ - apps::v1::StatefulSet, + apps::v1::{Deployment, StatefulSet}, core::v1::{ConfigMap, Service, ServiceAccount}, policy::v1::PodDisruptionBudget, rbac::v1::RoleBinding, @@ -37,12 +37,13 @@ use stackable_operator::{ use crate::{ controller::KAFKA_FULL_CONTROLLER_NAME, - crd::{KAFKA_OPERATOR_NAME, KafkaCluster, KafkaClusterVersion, v1alpha1}, + crd::{KAFKA_OPERATOR_NAME, KafkaCluster, KafkaClusterVersion, default_agent_image, v1alpha1}, webhooks::conversion::create_webhook_server, }; mod controller; mod crd; +mod framework; mod webhooks; mod built_info { @@ -67,6 +68,10 @@ struct Opts { struct KafkaRun { #[clap(flatten)] common: RunArguments, + + /// The agent image. Defaults to the agent image belonging to this operator release. + #[arg(long, env)] + agent_image: Option, } #[tokio::main] @@ -83,7 +88,7 @@ async fn main() -> anyhow::Result<()> { maintenance, common, }, - .. + agent_image, }) => { // NOTE (@NickLarsenNZ): Before stackable-telemetry was used: // - The console log level was set by `KAFKA_OPERATOR_LOG`, and is now `CONSOLE_LOG` (when using Tracing::pre_configured). @@ -171,6 +176,10 @@ async fn main() -> anyhow::Result<()> { watch_namespace.get_api::>(&client), watcher::Config::default(), ) + .owns( + watch_namespace.get_api::>(&client), + watcher::Config::default(), + ) .watches( watch_namespace.get_api::>(&client), watcher::Config::default(), @@ -188,6 +197,9 @@ async fn main() -> anyhow::Result<()> { controller::error_policy, Arc::new(controller::Ctx { client: client.clone(), + agent_image: agent_image.unwrap_or_else(|| { + default_agent_image(&operator_environment.image_repository) + }), operator_environment, }), ) From f15777c1e5bef9a0b90fbd2f44ce8555b91faa22 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Thu, 24 Sep 2026 16:39:54 +0200 Subject: [PATCH 03/25] add agent image and cluster role to Helm chart --- .../kafka-operator/templates/_helpers.tpl | 7 +++++++ .../templates/clusterrole-agent.yaml | 21 +++++++++++++++++++ .../templates/clusterrole-operator.yaml | 15 ++++++++++++- .../kafka-operator/templates/deployment.yaml | 8 +++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 deploy/helm/kafka-operator/templates/clusterrole-agent.yaml diff --git a/deploy/helm/kafka-operator/templates/_helpers.tpl b/deploy/helm/kafka-operator/templates/_helpers.tpl index 9c61cd511..27536afa2 100644 --- a/deploy/helm/kafka-operator/templates/_helpers.tpl +++ b/deploy/helm/kafka-operator/templates/_helpers.tpl @@ -84,3 +84,10 @@ Build the full operator container image reference. {{- define "kafka-operator.image" -}} {{- printf "%s/%s:%s" .Values.image.repository .Chart.Name (.Values.image.tag | default .Chart.AppVersion) -}} {{- end }} + +{{/* +Build the full agent container image reference. The agent is released together with the operator. +*/}} +{{- define "kafka-operator.agentImage" -}} +{{- printf "%s/%s-agent:%s" .Values.image.repository (include "kafka-operator.name" .) (.Values.image.tag | default .Chart.AppVersion) -}} +{{- end }} diff --git a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml new file mode 100644 index 000000000..8288ab33a --- /dev/null +++ b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml @@ -0,0 +1,21 @@ +--- +# Agent ClusterRole: bound (via per KafkaCluster RoleBinding) to the ServiceAccount that the +# platform-access agent pod runs as. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "kafka-operator.name" . }}-agent-clusterrole + labels: + {{- include "kafka-operator.labels" . | nindent 4 }} +rules: +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} + # On OpenShift, the agent pod must be allowed to use the nonroot-v2 SCC + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - nonroot-v2 + verbs: + - use +{{ end }} diff --git a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml index 59a34e6ce..96045367c 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml @@ -41,7 +41,7 @@ rules: - list - patch - watch - # Required to bind the product ClusterRole to the per-cluster ServiceAccount. + # Required to bind the product and agent ClusterRoles to the per-cluster ServiceAccounts. - apiGroups: - rbac.authorization.k8s.io resources: @@ -50,6 +50,7 @@ rules: - bind resourceNames: - {{ include "kafka-operator.name" . }}-clusterrole + - {{ include "kafka-operator.name" . }}-agent-clusterrole # StatefulSet created per role group (broker, KRaft controller). Applied via # SSA, tracked for orphan cleanup, and owned by the controller. - apiGroups: @@ -63,6 +64,18 @@ rules: - list - patch - watch + # Deployment of the platform-access agent. + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - watch # PodDisruptionBudget created per role group. Applied via SSA and tracked for orphan cleanup, and owned by the controller. - apiGroups: - policy diff --git a/deploy/helm/kafka-operator/templates/deployment.yaml b/deploy/helm/kafka-operator/templates/deployment.yaml index 6f7163dcd..9fac4f33b 100644 --- a/deploy/helm/kafka-operator/templates/deployment.yaml +++ b/deploy/helm/kafka-operator/templates/deployment.yaml @@ -16,6 +16,7 @@ spec: metadata: annotations: internal.stackable.tech/image: {{ include "kafka-operator.image" . }} + internal.stackable.tech/agent-image: {{ include "kafka-operator.agentImage" . }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -70,6 +71,13 @@ spec: - name: IMAGE_REPOSITORY value: {{ .Values.image.productRepository | default .Values.image.repository }} + # The image of the agent the operator deploys alongside a cluster. + - name: AGENT_IMAGE + # Tilt can use annotations as image paths, but not env variables + valueFrom: + fieldRef: + fieldPath: metadata.annotations['internal.stackable.tech/agent-image'] + # Operators need to know the node name they are running on, to e.g. discover the # Kubernetes domain name from the kubelet API. - name: KUBERNETES_NODE_NAME From ed51b0e91be5a2e028c95edf3faa171e10a5f705 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Thu, 24 Sep 2026 16:44:26 +0200 Subject: [PATCH 04/25] build a separate agent image --- .gitignore | 1 + Tiltfile | 17 ++++- default.nix | 36 ++++++++- docker/Dockerfile | 2 +- docker/Dockerfile.agent | 158 ++++++++++++++++++++++++++++++++++++++++ nix/meta.json | 2 +- 6 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 docker/Dockerfile.agent diff --git a/.gitignore b/.gitignore index 411cc85da..cc2e5c12e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ target/ *.tgz result +result-agent image.tar tilt_options.json diff --git a/Tiltfile b/Tiltfile index 1769d19a5..fba0c44f2 100644 --- a/Tiltfile +++ b/Tiltfile @@ -34,7 +34,22 @@ custom_build( # We need to set the correct image annotation on the operator Deployment to use e.g. # oci.stackable.tech/sandbox/opa-operator:7y19m3d8clwxlv34v5q2x4p7v536s00g instead of # oci.stackable.tech/sandbox/opa-operator:0.0.0-dev (which does not exist) -k8s_kind('Deployment', image_json_path='{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}') +deployment_image_json_paths = ['{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}'] + +# Operators that ship an agent (see `agent` in nix/meta.json) also build the agent image and pass +# it to the operator via the `internal.stackable.tech/agent-image` annotation. +if 'agent' in meta: + agent_image_name = operator_repository + '/' + meta['agent']['name'] + custom_build( + agent_image_name, + 'nix-build . -A dockerAgent --argstr dockerNameAgent "' + agent_image_name + '" -o result-agent && ./result-agent/load-image | docker load', + deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', "nix", 'build.rs', 'vendor'], + ignore=['*.~undo-tree~'], + outputs_image_ref_to='result-agent/ref', + ) + deployment_image_json_paths.append('{.spec.template.metadata.annotations.internal\\.stackable\\.tech/agent-image}') + +k8s_kind('Deployment', image_json_path=deployment_image_json_paths) k8s_kind('DaemonSet', image_json_path='{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}') # Optionally specify a custom Helm values file to be passed to the Helm deployment below. diff --git a/default.nix b/default.nix index 6feb190a3..abaa026b6 100644 --- a/default.nix +++ b/default.nix @@ -101,6 +101,8 @@ } , meta ? pkgsLocal.lib.importJSON ./nix/meta.json , dockerName ? "oci.stackable.tech/sandbox/${meta.operator.name}" +# Only used by operators that ship an agent (see `agent` in nix/meta.json) +, dockerNameAgent ? "oci.stackable.tech/sandbox/${meta.agent.name}" , dockerTag ? null # Controls the amount of debug information included in the built operator binaries, # see https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo @@ -125,7 +127,11 @@ rec { inherit cargo sources pkgsLocal pkgsTarget meta; inherit (pkgsLocal) lib; pkgs = lib.warn "pkgs is not cross-compilation-aware, explicitly use either pkgsLocal or pkgsTarget" pkgsLocal; - build = cargo.allWorkspaceMembers; + # Operators that ship an agent (see `agent` in nix/meta.json) keep the agent binary out of the + # operator image, as it has its own image (`dockerAgent`). + build = if meta ? agent + then cargo.workspaceMembers."stackable-${meta.operator.name}".build + else cargo.allWorkspaceMembers; entrypoint = build+"/bin/stackable-${meta.operator.name}"; # Run crds in the target environment, to avoid compiling everything twice crds = pkgsTarget.runCommand "${meta.operator.name}-crds.yaml" {} @@ -143,13 +149,13 @@ rec { # build it in the local environment so that the generated load-image # can run locally. # That's still fine, as long as we only refer to pkgsTarget *inside* of the image. - dockerImage = pkgsLocal.dockerTools.streamLayeredImage { + dockerImageArgs = { name = dockerName; tag = dockerTag; contents = [ # Kerberos 5 must be installed globally to load plugins correctly pkgsTarget.krb5 - # Make the whole cargo workspace available on $PATH + # Make the operator binaries available on $PATH build ] ++ lib.optional includeShell [ pkgsTarget.bashInteractive @@ -189,6 +195,7 @@ rec { User = toString stackableUserUid; }; }; + dockerImage = pkgsLocal.dockerTools.streamLayeredImage dockerImageArgs; docker = pkgsLocal.linkFarm "${dockerImage.name}-docker" [ { name = "load-image"; @@ -212,6 +219,29 @@ rec { } ]; + # The image of the agent, only built for operators that ship one. + dockerAgent = if meta ? agent then + let + agentBuild = cargo.workspaceMembers."stackable-${meta.agent.name}".build; + agentImage = pkgsLocal.dockerTools.streamLayeredImage (dockerImageArgs // { + name = dockerNameAgent; + contents = [ agentBuild ] ++ lib.optional includeShell [ + pkgsTarget.bashInteractive + pkgsTarget.coreutils + pkgsTarget.util-linuxMinimal + ]; + config = dockerImageArgs.config // { + Entrypoint = [ "${agentBuild}/bin/stackable-${meta.agent.name}" ]; + }; + }); + in pkgsLocal.linkFarm "${agentImage.name}-docker" [ + { name = "load-image"; path = agentImage; } + { name = "ref"; path = pkgsLocal.writeText "${agentImage.name}-image-tag" "${agentImage.imageName}:${agentImage.imageTag}"; } + { name = "image-repo"; path = pkgsLocal.writeText "${agentImage.name}-repo" agentImage.imageName; } + { name = "image-tag"; path = pkgsLocal.writeText "${agentImage.name}-tag" agentImage.imageTag; } + ] + else null; + # need to use vendored crate2nix because of https://github.com/kolloch/crate2nix/issues/264 crate2nix = import sources.crate2nix { pkgs = pkgsLocal; }; tilt = pkgsLocal.tilt; diff --git a/docker/Dockerfile b/docker/Dockerfile index 84458c3a2..a96fc6111 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -190,7 +190,7 @@ EOF COPY LICENSE /licenses/LICENSE -COPY --from=builder --chown=${STACKABLE_USER_UID}:0 /app/* /usr/local/bin/ +COPY --from=builder --chown=${STACKABLE_USER_UID}:0 /app/stackable-kafka-operator* /app/stackable-src.tar.gz /usr/local/bin/ USER ${STACKABLE_USER_UID} diff --git a/docker/Dockerfile.agent b/docker/Dockerfile.agent new file mode 100644 index 000000000..04f55b38d --- /dev/null +++ b/docker/Dockerfile.agent @@ -0,0 +1,158 @@ +# syntax=docker/dockerfile:1.16.0@sha256:e2dd261f92e4b763d789984f6eab84be66ab4f5f08052316d8eb8f173593acf7 +# NOTE: The syntax directive needs to be the first line in a Dockerfile +# Find the latest versions here: https://hub.docker.com/r/docker/dockerfile/tags +# And the changelogs: https://docs.docker.com/build/buildkit/dockerfile-release-notes/ or https://github.com/moby/buildkit/releases + +# https://docs.docker.com/build/checks/#fail-build-on-check-violations +# check=error=true + +# We want to automatically use the latest. We also don't tag our images with a version. +# hadolint ignore=DL3007 +FROM oci.stackable.tech/sdp/ubi10-rust-builder:latest AS builder + + +# We want to automatically use the latest. +# hadolint ignore=DL3007 +FROM registry.access.redhat.com/ubi10/ubi-minimal:latest AS agent + +ARG VERSION +# NOTE (@Techassi): This is required for OpenShift/Red Hat certification +# Keeping this as "1" seems to be fine since a couple of years /shrug +ARG RELEASE="1" + +# These are chosen at random and are this high on purpose to have very little chance to clash with an existing user or group on the host system +# NOTE: Please also update default.nix accordingly! +ARG STACKABLE_USER_GID="574654813" +ARG STACKABLE_USER_UID="782252253" +ARG STACKABLE_USER_NAME="stackable" + +# Sets the default shell to Bash with strict error handling and robust pipeline processing. +# "-e": Exits immediately if a command exits with a non-zero status +# "-u": Treats unset variables as an error, preventing unexpected behavior from undefined variables. +# "-o pipefail": Causes a pipeline to return the exit status of the last command in the pipe that failed, ensuring errors in any part of a pipeline are not ignored. +# "-c": Allows the execution of commands passed as a string +SHELL ["/bin/bash", "-euo", "pipefail", "-c"] + +# These labels have mostly been superseded by the OpenContainer spec annotations below but it doesn't hurt to include them +# http://label-schema.org/rc1/ +LABEL name="Stackable Agent for Apache Kafka" +LABEL maintainer="info@stackable.tech" +LABEL vendor="Stackable GmbH" +LABEL version="${VERSION}" +LABEL release="${RELEASE}" +LABEL summary="Manage resources inside Apache Kafka clusters." +LABEL description="Manage resources inside Apache Kafka clusters." + +# Overwriting/Pinning UBI labels +# https://github.com/projectatomic/ContainerApplicationGenericLabels +LABEL vcs-ref="" +LABEL distribution-scope="public" +LABEL url="https://stackable.tech" +ARG TARGETARCH +LABEL architecture="${TARGETARCH}" +LABEL com.redhat.component="" +# It complains about it being an invalid label but RedHat uses it and we want to override it and it works.... +# hadolint ignore=DL3048 +LABEL com.redhat.license_terms="" +LABEL io.buildah.version="" +LABEL io.openshift.expose-services="" + +# https://github.com/opencontainers/image-spec/blob/64294bd7a2bf2537e1a6a34d687caae70300b0c4/annotations.md#annotations +LABEL org.opencontainers.image.authors="info@stackable.tech" +LABEL org.opencontainers.image.url="https://stackable.tech" +LABEL org.opencontainers.image.vendor="Stackable GmbH" +LABEL org.opencontainers.image.licenses="OSL-3.0" +LABEL org.opencontainers.image.documentation="https://docs.stackable.tech/home/stable/kafka/" +LABEL org.opencontainers.image.version="${VERSION}" +LABEL org.opencontainers.image.revision="${RELEASE}" +LABEL org.opencontainers.image.title="Stackable Agent for Apache Kafka" +LABEL org.opencontainers.image.description="Manage resources inside Apache Kafka clusters." + +# https://docs.openshift.com/container-platform/4.16/openshift_images/create-images.html#defining-image-metadata +# https://github.com/projectatomic/ContainerApplicationGenericLabels/blob/master/vendor/redhat/labels.md +LABEL io.openshift.tags="ubi10,stackable,sdp,kafka" +LABEL io.k8s.description="Manage resources inside Apache Kafka clusters." +LABEL io.k8s.display-name="Stackable Agent for Apache Kafka" + +COPY <> /stackable/.bashrc + +echo -e "if [ -f ~/.bashrc ]; then\n\tsource ~/.bashrc\nfi" >> /stackable/.profile + +chown ${STACKABLE_USER_UID}:0 /stackable/.bashrc +chown ${STACKABLE_USER_UID}:0 /stackable/.profile + +# All files and folders owned by root to support running as arbitrary users +# This is best practice as all container users will belong to the root group (0) +chown -R ${STACKABLE_USER_UID}:0 /stackable +chmod -R g=u /stackable +EOF + +COPY < Date: Thu, 24 Sep 2026 19:47:34 +0200 Subject: [PATCH 05/25] run ghs build for matrix of operator and agent --- .github/workflows/build.yaml | 42 ++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7251f20b1..2c6cc0009 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,8 +62,22 @@ jobs: - '**/Cargo.toml' - 'Cargo.lock' - '**/*.rs' + - 'nix/meta.json' + + # Operators that ship an agent (see `agent` in nix/meta.json) also build and publish its image. + - name: Determine Container Images + id: images + shell: bash + run: | + set -euo pipefail + IMAGES=$(jq -c --arg operator "$OPERATOR_NAME" ' + [{component: "operator", name: $operator, "container-file": "docker/Dockerfile"}] + + if .agent then [{component: "agent", name: .agent.name, "container-file": "docker/Dockerfile.agent"}] else [] end + ' nix/meta.json) + echo "IMAGES=$IMAGES" | tee -a "$GITHUB_OUTPUT" outputs: detected: ${{ steps.check.outputs.detected }} + images: ${{ steps.images.outputs.IMAGES }} helm-lint: name: Lint Helm Chart @@ -131,7 +145,7 @@ jobs: run: cargo udeps --workspace --all-targets build-container-image: - name: Build/Publish ${{ matrix.runner.arch }} Image + name: Build/Publish ${{ matrix.image.component }} ${{ matrix.runner.arch }} Image if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -146,6 +160,7 @@ jobs: runner: - { name: "ubuntu-latest", arch: "amd64" } - { name: "ubicloud-standard-8-arm", arch: "arm64" } + image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ${{ matrix.runner.name }} outputs: operator-version: ${{ steps.version.outputs.OPERATOR_VERSION }} @@ -208,10 +223,10 @@ jobs: id: build uses: stackabletech/actions/build-container-image@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-name: ${{ env.OPERATOR_NAME }} + image-name: ${{ matrix.image.name }} image-index-manifest-tag: ${{ steps.version.outputs.OPERATOR_VERSION }} build-arguments: VERSION=${{ steps.version.outputs.OPERATOR_VERSION }} - container-file: docker/Dockerfile + container-file: ${{ matrix.image.container-file }} - name: Publish Container Image to oci.stackable.tech if: ${{ !github.event.pull_request.head.repo.fork }} @@ -220,7 +235,7 @@ jobs: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build image-registry-password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: sdp/${{ env.OPERATOR_NAME }} + image-repository: sdp/${{ matrix.image.name }} canonical-image-manifest-tag: ${{ steps.build.outputs.image-manifest-tag }} canonical-source-image-uri: ${{ steps.build.outputs.image-manifest-uri }} @@ -231,12 +246,12 @@ jobs: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build image-registry-password: ${{ secrets.QUAY_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: stackable/sdp/${{ env.OPERATOR_NAME }} + image-repository: stackable/sdp/${{ matrix.image.name }} canonical-image-manifest-tag: ${{ steps.build.outputs.image-manifest-tag }} canonical-source-image-uri: ${{ steps.build.outputs.image-manifest-uri }} publish-index-manifest: - name: Publish/Sign ${{ needs.build-container-image.outputs.operator-version }} Index + name: Publish/Sign ${{ matrix.image.component }} ${{ needs.build-container-image.outputs.operator-version }} Index if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -248,6 +263,10 @@ jobs: permissions: contents: read id-token: write + strategy: + fail-fast: false + matrix: + image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ubuntu-latest steps: - name: Checkout Repository @@ -261,7 +280,7 @@ jobs: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build image-registry-password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: sdp/${{ env.OPERATOR_NAME }} + image-repository: sdp/${{ matrix.image.name }} canonical-image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} - name: Publish and Sign Image Index to quay.io @@ -270,7 +289,7 @@ jobs: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build image-registry-password: ${{ secrets.QUAY_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: stackable/sdp/${{ env.OPERATOR_NAME }} + image-repository: stackable/sdp/${{ matrix.image.name }} canonical-image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} publish-helm-chart: @@ -320,7 +339,7 @@ jobs: helm-version: v3.17.4 # This is currently the latest version which supports pushing to quay.io openshift-preflight-check: - name: Run OpenShift Preflight Check for ${{ needs.build-container-image.outputs.operator-version }}-${{ matrix.arch }} + name: Run OpenShift Preflight Check for ${{ matrix.image.component }} ${{ needs.build-container-image.outputs.operator-version }}-${{ matrix.arch }} if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -336,18 +355,19 @@ jobs: arch: - amd64 - arm64 + image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ubuntu-latest steps: - name: Run OpenShift Preflight Check for oci.stackable.tech uses: stackabletech/actions/run-openshift-preflight@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-index-uri: oci.stackable.tech/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} + image-index-uri: oci.stackable.tech/sdp/${{ matrix.image.name }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} - name: Run OpenShift Preflight Check for quay.io uses: stackabletech/actions/run-openshift-preflight@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-index-uri: quay.io/stackable/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} + image-index-uri: quay.io/stackable/sdp/${{ matrix.image.name }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} # This job is a required check in GitHub Settings for this repository. From 177cfb18a49a1bcce842bc0b0d74ac84bd02f29d Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Thu, 1 Oct 2026 14:16:33 +0200 Subject: [PATCH 06/25] move staged framework code to operator-rs --- Cargo.lock | 87 +++++----- Cargo.nix | 154 ++++++++---------- Cargo.toml | 2 +- crate-hashes.json | 18 +- extra/crds.yaml | 2 +- rust/agent-binary/src/framework/mod.rs | 12 -- rust/agent-binary/src/main.rs | 15 +- .../src/controller/build/mod.rs | 5 +- rust/operator-binary/src/crd/mod.rs | 13 +- .../src/framework/commons/mod.rs | 1 - .../framework/commons/platform_access/mod.rs | 3 - .../framework/commons/platform_access/tls.rs | 87 ---------- .../src/framework/constants/mod.rs | 1 - .../src/framework/constants/secret.rs | 2 - .../src/framework/kvp/label.rs | 45 ----- rust/operator-binary/src/framework/kvp/mod.rs | 1 - rust/operator-binary/src/framework/mod.rs | 6 - rust/operator-binary/src/main.rs | 3 +- .../src/webhooks/conversion.rs | 11 +- 19 files changed, 138 insertions(+), 330 deletions(-) delete mode 100644 rust/agent-binary/src/framework/mod.rs delete mode 100644 rust/operator-binary/src/framework/commons/mod.rs delete mode 100644 rust/operator-binary/src/framework/commons/platform_access/mod.rs delete mode 100644 rust/operator-binary/src/framework/commons/platform_access/tls.rs delete mode 100644 rust/operator-binary/src/framework/constants/mod.rs delete mode 100644 rust/operator-binary/src/framework/constants/secret.rs delete mode 100644 rust/operator-binary/src/framework/kvp/label.rs delete mode 100644 rust/operator-binary/src/framework/kvp/mod.rs delete mode 100644 rust/operator-binary/src/framework/mod.rs diff --git a/Cargo.lock b/Cargo.lock index b08d28809..77847b010 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -439,22 +439,13 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +checksum = "1af709f1f33454bf52eadfc8c78b3b9ef9cb26fb54d16dc9cd9a7299f899fd1b" dependencies = [ "unicode-segmentation", ] -[[package]] -name = "convert_case_extras" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589c70f0faf8aa9d17787557d5eae854d7755cac50f5c3d12c81d3d57661cebb" -dependencies = [ - "convert_case", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -773,9 +764,9 @@ dependencies = [ [[package]] name = "educe" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e451fac8dd8dece16234604bf1efce6e90fddd8ab6ad4d66eec0eca5160959dd" +checksum = "1ebdb1f8f8d2815bbe7b369a7da10343c82026a4503b68bd1279ba557611e96d" dependencies = [ "enum-ordinalize", "proc-macro2", @@ -1707,7 +1698,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "darling 0.24.1", "regex", @@ -1978,7 +1969,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.7", + "rand 0.8.8", "smallvec", "zeroize", ] @@ -2038,9 +2029,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opentelemetry" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" +checksum = "6cdb0b1b267eb9db3331b434ed9ddab10d50e280a9adf9d13e5233e2002b61b5" dependencies = [ "futures-core", "futures-sink", @@ -2052,9 +2043,9 @@ dependencies = [ [[package]] name = "opentelemetry-appender-tracing" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0080f0dc1d7c786f467cd85a4e395fcab11ee852004f39a29a18ab7c25d837" +checksum = "e2b304e8d8f11326ba366a99ca5c7aaf7cd397b67268a332437175aeb42a40db" dependencies = [ "opentelemetry", "tracing", @@ -2064,9 +2055,9 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" +checksum = "ee2c3625b8aa04209f7e01e513bc8044da9687fa38a9eacf59628ca5f3b87300" dependencies = [ "async-trait", "bytes", @@ -2077,11 +2068,12 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" +checksum = "699a67345e21962a231955b9059a157e428b219fa5df8efe11f08346fb23a344" dependencies = [ "http", + "httpdate", "opentelemetry", "opentelemetry-http", "opentelemetry-proto", @@ -2096,9 +2088,9 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" +checksum = "25da1ac11a0aeccf38d7f77ee0348715adaf8340f65ad46c94a02c6b20e2f65d" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -2109,15 +2101,15 @@ dependencies = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c913ac17a6c451661ee255f4625d143e51647ae78ebd969b75e41c4442f4fe47" +checksum = "d288b1e1bc3590052fbb8f0f635ef248dd9022cf1fbaeb6582b7ad6081a17b87" [[package]] name = "opentelemetry_sdk" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" +checksum = "cb39533d9d1c912123efd7d41d7e0c29d16917b60ce15b4c8d87cb1af7f67520" dependencies = [ "futures-channel", "futures-executor", @@ -2422,9 +2414,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "rand_chacha 0.3.1", "rand_core 0.6.4", @@ -3152,7 +3144,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "const-oid", "ecdsa", @@ -3209,15 +3201,15 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.118.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +version = "0.119.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "base64 0.23.1", "clap", "const_format", "delegate", "dockerfile-parser", - "educe 0.7.6", + "educe 0.8.1", "either", "futures", "http", @@ -3254,7 +3246,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3265,7 +3257,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "jiff", "k8s-openapi", @@ -3282,7 +3274,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "axum", "clap", @@ -3306,7 +3298,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "kube", "schemars", @@ -3320,10 +3312,9 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "convert_case", - "convert_case_extras", "darling 0.24.1", "indoc", "itertools 0.15.0", @@ -3337,8 +3328,8 @@ dependencies = [ [[package]] name = "stackable-webhook" -version = "0.9.2" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1" +version = "0.10.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" dependencies = [ "arc-swap", "async-trait", @@ -3361,7 +3352,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower", - "tower-http 0.7.0", + "tower-http 0.7.1", "tracing", "tracing-opentelemetry", "x509-cert", @@ -3754,9 +3745,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233" +checksum = "08a05a66a4fdd61cbbe0a1d755ffe0ca6aba159dd4820936a0ff8a8278245b9c" dependencies = [ "bitflags 2.13.1", "bytes", @@ -3840,9 +3831,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" +checksum = "0a904802a1b902f43638b677ff2a650847e3b4404101b6c586d648e8c1e3e8fe" dependencies = [ "js-sys", "opentelemetry", diff --git a/Cargo.nix b/Cargo.nix index 292f308c7..0f1de0737 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -1376,9 +1376,9 @@ rec { }; "convert_case" = rec { crateName = "convert_case"; - version = "0.11.0"; + version = "0.12.0"; edition = "2021"; - sha256 = "0jfv1ajyr65bjlx533n5alfkfjdl8ks4zxfywdiz1jnj1qcz1yxg"; + sha256 = "06zxk7w9jwlsrp4nvlalzckcpycy7f5wgj6zx99bym1lygqhkxqs"; authors = [ "rutrum " ]; @@ -1390,25 +1390,6 @@ rec { ]; }; - "convert_case_extras" = rec { - crateName = "convert_case_extras"; - version = "0.2.0"; - edition = "2021"; - sha256 = "1fyfc5vdblw15k8w7xahmif7bmslx3mdamvmg0brvapqzbq7172q"; - authors = [ - "rutrum " - ]; - dependencies = [ - { - name = "convert_case"; - packageId = "convert_case"; - } - ]; - features = { - "rand" = [ "dep:rand" ]; - "random" = [ "rand" ]; - }; - }; "core-foundation" = rec { crateName = "core-foundation"; version = "0.10.1"; @@ -2378,11 +2359,11 @@ rec { }; resolvedDefaultFeatures = [ "Clone" "Debug" "Hash" "PartialEq" ]; }; - "educe 0.7.6" = rec { + "educe 0.8.1" = rec { crateName = "educe"; - version = "0.7.6"; + version = "0.8.1"; edition = "2024"; - sha256 = "1par14babv60xrk4vbdnibfzv43frvpz2jv06iif3v4dvp4gllg4"; + sha256 = "0vg925v5bfkr2aynhfshlhk21j230fhpv6ingfz5p0fjz3wb3g8y"; procMacro = true; authors = [ "Magic Len " @@ -2405,13 +2386,7 @@ rec { { name = "syn"; packageId = "syn 3.0.4"; - } - ]; - devDependencies = [ - { - name = "syn"; - packageId = "syn 3.0.4"; - features = [ "full" ]; + features = [ "visit" "visit-mut" ]; } ]; features = { @@ -5410,7 +5385,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -6459,7 +6434,7 @@ rec { } { name = "rand"; - packageId = "rand 0.8.7"; + packageId = "rand 0.8.8"; optional = true; usesDefaultFeatures = false; } @@ -6478,7 +6453,7 @@ rec { devDependencies = [ { name = "rand"; - packageId = "rand 0.8.7"; + packageId = "rand 0.8.8"; features = [ "small_rng" ]; } ]; @@ -6625,9 +6600,9 @@ rec { }; "opentelemetry" = rec { crateName = "opentelemetry"; - version = "0.32.0"; + version = "0.33.0"; edition = "2021"; - sha256 = "10ln14d1jgc8rvw97mblc9blzcgpg1bimim4d170b7ia4mijq55h"; + sha256 = "1db15c0f4csj7v8zkbd9h3i503divafysd5l64rxpfby4qdhpnvc"; dependencies = [ { name = "futures-core"; @@ -6679,9 +6654,9 @@ rec { }; "opentelemetry-appender-tracing" = rec { crateName = "opentelemetry-appender-tracing"; - version = "0.32.0"; + version = "0.33.0"; edition = "2021"; - sha256 = "0dyq4myan64sl8wly02jx0gb3jjz7575mn3w8rpphz0xvkq8001c"; + sha256 = "1ns05asawxbi8cra6s3jnsbx6z5gg9fcm6ba6sx2c4ziv3l09cz2"; libName = "opentelemetry_appender_tracing"; dependencies = [ { @@ -6730,9 +6705,9 @@ rec { }; "opentelemetry-http" = rec { crateName = "opentelemetry-http"; - version = "0.32.0"; + version = "0.33.0"; edition = "2021"; - sha256 = "0ca3drvm4fx5nskl7yn42dimy3bg35ppzc85y1p27pz215fh30sn"; + sha256 = "003kp3rsb332b77yma9qza3rdnj4h2y17r81gsgj015ap0jkcb7f"; libName = "opentelemetry_http"; dependencies = [ { @@ -6768,16 +6743,15 @@ rec { "internal-logs" = [ "opentelemetry/internal-logs" ]; "reqwest" = [ "dep:reqwest" ]; "reqwest-blocking" = [ "dep:reqwest" "reqwest/blocking" ]; - "reqwest-rustls" = [ "dep:reqwest" "reqwest/default-tls" ]; - "reqwest-rustls-webpki-roots" = [ "dep:reqwest" "reqwest/default-tls" "reqwest/webpki-roots" ]; + "reqwest-rustls" = [ "dep:reqwest" "reqwest/rustls" ]; }; resolvedDefaultFeatures = [ "reqwest" "reqwest-blocking" ]; }; "opentelemetry-otlp" = rec { crateName = "opentelemetry-otlp"; - version = "0.32.0"; + version = "0.33.0"; edition = "2021"; - sha256 = "0d9cys2flpidfxbr6h1103hjc633cax47ihnqgbj0xnicscr4rlr"; + sha256 = "0i534gxld0zh27z8xpx5kwhqnhky2nd0bfam34ijm5i1bqs6g6k9"; libName = "opentelemetry_otlp"; dependencies = [ { @@ -6787,6 +6761,11 @@ rec { usesDefaultFeatures = false; features = [ "std" ]; } + { + name = "httpdate"; + packageId = "httpdate"; + optional = true; + } { name = "opentelemetry"; packageId = "opentelemetry"; @@ -6829,7 +6808,7 @@ rec { packageId = "tokio"; optional = true; usesDefaultFeatures = false; - features = [ "sync" "rt" ]; + features = [ "sync" "rt" "time" ]; } { name = "tonic"; @@ -6865,17 +6844,15 @@ rec { ]; features = { "default" = [ "http-proto" "reqwest-blocking-client" "trace" "metrics" "logs" "internal-logs" ]; - "experimental-grpc-retry" = [ "grpc-tonic" "opentelemetry_sdk/experimental_async_runtime" "opentelemetry_sdk/rt-tokio" ]; - "experimental-http-retry" = [ "opentelemetry_sdk/experimental_async_runtime" "opentelemetry_sdk/rt-tokio" "tokio" "httpdate" ]; "flate2" = [ "dep:flate2" ]; "grpc-tonic" = [ "tonic" "tonic-types" "prost" "http" "tokio" "opentelemetry-proto/gen-tonic" ]; "gzip-http" = [ "flate2" ]; "gzip-tonic" = [ "tonic/gzip" ]; "http" = [ "dep:http" ]; - "http-json" = [ "serde_json" "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "opentelemetry-proto/with-serde" "http" "trace" "metrics" ]; - "http-proto" = [ "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "http" "trace" "metrics" ]; + "http-json" = [ "serde_json" "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "opentelemetry-proto/with-serde" "http" "httpdate" "trace" "metrics" ]; + "http-proto" = [ "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "http" "httpdate" "trace" "metrics" ]; "httpdate" = [ "dep:httpdate" ]; - "hyper-client" = [ "opentelemetry-http/hyper" ]; + "hyper-client" = [ "opentelemetry-http/hyper" "tokio" ]; "integration-testing" = [ "tonic" "prost" "tokio/full" "trace" "logs" ]; "internal-logs" = [ "opentelemetry_sdk/internal-logs" "opentelemetry/internal-logs" ]; "logs" = [ "opentelemetry/logs" "opentelemetry_sdk/logs" "opentelemetry-proto/logs" ]; @@ -6884,13 +6861,9 @@ rec { "prost" = [ "dep:prost" ]; "reqwest" = [ "dep:reqwest" ]; "reqwest-blocking-client" = [ "reqwest/blocking" "opentelemetry-http/reqwest-blocking" ]; - "reqwest-client" = [ "reqwest" "opentelemetry-http/reqwest" ]; + "reqwest-client" = [ "reqwest" "opentelemetry-http/reqwest" "tokio" ]; "reqwest-rustls" = [ "reqwest" "opentelemetry-http/reqwest-rustls" ]; - "reqwest-rustls-webpki-roots" = [ "reqwest" "opentelemetry-http/reqwest-rustls-webpki-roots" ]; - "serde" = [ "dep:serde" ]; "serde_json" = [ "dep:serde_json" ]; - "serialize" = [ "serde" "serde_json" ]; - "tls" = [ "tls-ring" ]; "tls-aws-lc" = [ "tonic/tls-aws-lc" ]; "tls-provider-agnostic" = [ "tonic/_tls-any" ]; "tls-ring" = [ "tonic/tls-ring" ]; @@ -6904,13 +6877,13 @@ rec { "zstd-http" = [ "zstd" ]; "zstd-tonic" = [ "tonic/zstd" ]; }; - resolvedDefaultFeatures = [ "default" "grpc-tonic" "gzip-tonic" "http" "http-proto" "internal-logs" "logs" "metrics" "opentelemetry-http" "prost" "reqwest" "reqwest-blocking-client" "tokio" "tonic" "tonic-types" "trace" ]; + resolvedDefaultFeatures = [ "default" "grpc-tonic" "gzip-tonic" "http" "http-proto" "httpdate" "internal-logs" "logs" "metrics" "opentelemetry-http" "prost" "reqwest" "reqwest-blocking-client" "tokio" "tonic" "tonic-types" "trace" ]; }; "opentelemetry-proto" = rec { crateName = "opentelemetry-proto"; - version = "0.32.0"; + version = "0.33.0"; edition = "2021"; - sha256 = "0f5ny4rpnpq6q5q34b8k2q548rf31rpbxkwjqjwzfqxg3yx5imjn"; + sha256 = "0pgnw8h6nb50jind8npn821szb8mhwsf0zppswwczv0a3b0imni5"; libName = "opentelemetry_proto"; dependencies = [ { @@ -6974,9 +6947,9 @@ rec { }; "opentelemetry-semantic-conventions" = rec { crateName = "opentelemetry-semantic-conventions"; - version = "0.32.1"; + version = "0.33.0"; edition = "2021"; - sha256 = "0izyyi148774fndrdgcfwxx68l9y2ifn5x2mw8g6clf4lqbsq4y9"; + sha256 = "11vvl60n1bdph9jypfhzrwi91pa8y9g663wgpcphb41mpkhv326j"; libName = "opentelemetry_semantic_conventions"; features = { }; @@ -6984,21 +6957,24 @@ rec { }; "opentelemetry_sdk" = rec { crateName = "opentelemetry_sdk"; - version = "0.32.1"; + version = "0.33.0"; edition = "2021"; - sha256 = "1ycl11syranrinhgn4c2hlzhyzyvpa06ryxq5mxgzmf4387ghncv"; + sha256 = "083myvvimjw7im65pq8cnqbnkl991iz1vm6pxwij348wklym6ffb"; dependencies = [ { name = "futures-channel"; packageId = "futures-channel"; + optional = true; } { name = "futures-executor"; packageId = "futures-executor"; + optional = true; } { name = "futures-util"; packageId = "futures-util"; + optional = true; usesDefaultFeatures = false; features = [ "std" "sink" "async-await-macro" ]; } @@ -7029,6 +7005,7 @@ rec { { name = "thiserror"; packageId = "thiserror 2.0.20"; + optional = true; usesDefaultFeatures = false; } { @@ -7053,6 +7030,7 @@ rec { ]; features = { "default" = [ "trace" "metrics" "logs" "internal-logs" ]; + "experimental_async_runtime" = [ "dep:futures-channel" "dep:futures-executor" "dep:futures-util" "dep:thiserror" ]; "experimental_logs_batch_log_processor_with_async_runtime" = [ "logs" "experimental_async_runtime" ]; "experimental_metrics_bound_instruments" = [ "metrics" "opentelemetry/experimental_metrics_bound_instruments" ]; "experimental_metrics_custom_reader" = [ "metrics" ]; @@ -7062,8 +7040,8 @@ rec { "http" = [ "dep:http" ]; "internal-logs" = [ "opentelemetry/internal-logs" ]; "jaeger_remote_sampler" = [ "trace" "opentelemetry-http" "http" "serde" "serde_json" "url" "experimental_async_runtime" ]; - "logs" = [ "opentelemetry/logs" ]; - "metrics" = [ "opentelemetry/metrics" ]; + "logs" = [ "opentelemetry/logs" "dep:futures-channel" "dep:futures-executor" "dep:futures-util" ]; + "metrics" = [ "opentelemetry/metrics" "dep:futures-channel" "dep:futures-executor" "dep:futures-util" "dep:thiserror" ]; "opentelemetry-http" = [ "dep:opentelemetry-http" ]; "percent-encoding" = [ "dep:percent-encoding" ]; "rand" = [ "dep:rand" ]; @@ -7075,7 +7053,7 @@ rec { "testing" = [ "opentelemetry/testing" "trace" "metrics" "logs" "tokio/sync" ]; "tokio" = [ "dep:tokio" ]; "tokio-stream" = [ "dep:tokio-stream" ]; - "trace" = [ "opentelemetry/trace" "rand" "percent-encoding" ]; + "trace" = [ "opentelemetry/trace" "rand" "percent-encoding" "dep:futures-channel" "dep:futures-executor" "dep:futures-util" "dep:thiserror" ]; "url" = [ "dep:url" ]; }; resolvedDefaultFeatures = [ "default" "experimental_async_runtime" "internal-logs" "logs" "metrics" "percent-encoding" "rand" "rt-tokio" "tokio" "tokio-stream" "trace" ]; @@ -7901,11 +7879,11 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" "std_rng" "sys_rng" "thread_rng" ]; }; - "rand 0.8.7" = rec { + "rand 0.8.8" = rec { crateName = "rand"; - version = "0.8.7"; + version = "0.8.8"; edition = "2018"; - sha256 = "06iaf16fr0z8zly7anmn8ky0p80xnx9yv0gdcm30fwn9vqmigxi2"; + sha256 = "0k3d9psya5icpiylff1w1wjbnc3q4pb1953n1iw7gbr61ggcfn70"; authors = [ "The Rand Project Developers" "The Rust Project Developers" @@ -10325,7 +10303,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10563,12 +10541,12 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.118.0"; + version = "0.119.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10599,7 +10577,7 @@ rec { } { name = "educe"; - packageId = "educe 0.7.6"; + packageId = "educe 0.8.1"; usesDefaultFeatures = false; features = [ "Clone" "Debug" "Default" "PartialEq" "Eq" ]; } @@ -10767,7 +10745,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10802,7 +10780,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10883,7 +10861,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -10993,7 +10971,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11043,7 +11021,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11056,10 +11034,6 @@ rec { name = "convert_case"; packageId = "convert_case"; } - { - name = "convert_case_extras"; - packageId = "convert_case_extras"; - } { name = "darling"; packageId = "darling 0.24.1"; @@ -11106,12 +11080,12 @@ rec { }; "stackable-webhook" = rec { crateName = "stackable-webhook"; - version = "0.9.2"; + version = "0.10.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "bc6c84025c2dcc834b94bfb57ec72810ae5f5eb1"; + rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; @@ -11217,7 +11191,7 @@ rec { } { name = "tower-http"; - packageId = "tower-http 0.7.0"; + packageId = "tower-http 0.7.1"; features = [ "trace" ]; } { @@ -11422,7 +11396,7 @@ rec { "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sync_wrapper" = rec { crateName = "sync_wrapper"; @@ -12588,11 +12562,11 @@ rec { }; resolvedDefaultFeatures = [ "auth" "base64" "default" "follow-redirect" "futures-util" "map-response-body" "mime" "tower" "trace" "tracing" "util" "validate-request" ]; }; - "tower-http 0.7.0" = rec { + "tower-http 0.7.1" = rec { crateName = "tower-http"; - version = "0.7.0"; + version = "0.7.1"; edition = "2018"; - sha256 = "0cz2k1a6gj54lcqx9cxb6k7rfgwcgc2zi31xnq0vxhmh2blpa7xi"; + sha256 = "172v4iw852pzl0v0k0nlklavlsnaw3zmbmx1w2xirmpxlik5m808"; libName = "tower_http"; authors = [ "Tower Maintainers " @@ -12890,9 +12864,9 @@ rec { }; "tracing-opentelemetry" = rec { crateName = "tracing-opentelemetry"; - version = "0.33.0"; + version = "0.34.0"; edition = "2021"; - sha256 = "09nvxy5m7nxmifz4b6szdcyczapp2jcgxcac0jw4ax8klz5n9g5d"; + sha256 = "1zp8wg0yhj6nhv2vc0a182sf6iq8clmgyxxn70vg80mrl414i40a"; libName = "tracing_opentelemetry"; dependencies = [ { diff --git a/Cargo.toml b/Cargo.toml index 5e9c33132..8f9321a8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" repository = "https://github.com/stackabletech/kafka-operator" [workspace.dependencies] -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.118.0", features = ["crds", "webhook"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", branch = "feat/platform-access", features = ["crds", "webhook"] } anyhow = "1.0" built = { version = "0.8", features = ["chrono", "git2"] } diff --git a/crate-hashes.json b/crate-hashes.json index 8357dcf27..e4f5f7b1d 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,11 +1,11 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#k8s-version@0.1.3": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-certs@0.4.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-operator-derive@0.3.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-operator@0.118.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-shared@0.1.2": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-telemetry@0.6.5": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-versioned-macros@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-versioned@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.118.0#stackable-webhook@0.9.2": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci" + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.3": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.119.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.1.2": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci" } \ No newline at end of file diff --git a/extra/crds.yaml b/extra/crds.yaml index 7c5f5161f..eb762d076 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -2156,7 +2156,7 @@ spec: properties: secret: description: |- - A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), such as a + A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), e.g. as a Secret of type `kubernetes.io/tls`. maxLength: 253 minLength: 1 diff --git a/rust/agent-binary/src/framework/mod.rs b/rust/agent-binary/src/framework/mod.rs deleted file mode 100644 index c26b5e711..000000000 --- a/rust/agent-binary/src/framework/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Reusable, product-agnostic agent building blocks. Staged here until they move to operator-rs. - -use clap::Args; -use stackable_operator::cli::CommonOptions; - -/// Agent subcommands. Like [`stackable_operator::cli::Command`], but without `crd` as CRDs are only -/// deployed by operators. -#[derive(Debug, clap::Parser)] -pub enum AgentCommand { - /// Run the agent. - Run(Run), -} diff --git a/rust/agent-binary/src/main.rs b/rust/agent-binary/src/main.rs index 6ab5c58f7..0934f803f 100644 --- a/rust/agent-binary/src/main.rs +++ b/rust/agent-binary/src/main.rs @@ -1,11 +1,11 @@ //! The Stackable Kafka agent: a per-cluster controller that reconciles in-cluster resources like `KafkaTopic`s. use clap::Parser; -use stackable_operator::{cli::CommonOptions, telemetry::Tracing, utils::signal::SignalWatcher}; - -use crate::framework::AgentCommand; - -mod framework; +use stackable_operator::{ + cli::{Command, CommonOptions}, + telemetry::Tracing, + utils::signal::SignalWatcher, +}; mod built_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); @@ -15,13 +15,14 @@ mod built_info { #[clap(about, author)] struct Opts { #[clap(subcommand)] - cmd: AgentCommand, + cmd: Command, } #[tokio::main] async fn main() -> anyhow::Result<()> { match Opts::parse().cmd { - AgentCommand::Run(CommonOptions { telemetry, .. }) => { + Command::Crd => anyhow::bail!("this agent has no CRDs, they are owned by the operator"), + Command::Run(CommonOptions { telemetry, .. }) => { let _tracing_guard = Tracing::pre_configured(built_info::PKG_NAME, telemetry).init()?; tracing::info!( diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index 2283c4448..18e220a57 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -30,7 +30,6 @@ use crate::{ }, }, crd::role::{AnyConfig, KafkaRole}, - framework::kvp::label as framework_label, }; pub mod command; @@ -186,7 +185,7 @@ pub(crate) fn recommended_labels_for_cluster_resources(cluster: &ValidatedCluste } pub(crate) fn recommended_labels_for_agent_resources(cluster: &ValidatedCluster) -> Labels { - framework_label::recommended_labels_for_agent_resources( + label::recommended_labels_for_agent_resources( &cluster.name, &PRODUCT_NAME, &cluster.product_version, @@ -242,7 +241,7 @@ pub(crate) fn recommended_labels_for_unversioned_role_group_resources( /// Selector labels matching the pods of a role group. pub(crate) fn agent_selector(cluster: &ValidatedCluster) -> Labels { - framework_label::agent_selector(&cluster.name, &PRODUCT_NAME) + label::agent_selector(&cluster.name, &PRODUCT_NAME) } pub(crate) fn role_group_selector( diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 5af1e5428..7f486d93b 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -13,7 +13,7 @@ use snafu::Snafu; use stackable_operator::{ commons::{ cluster_operation::ClusterOperation, networking::DomainName, - product_image_selection::ProductImage, + platform_access::tls::TlsClientCredential, product_image_selection::ProductImage, }, config::merge::Merge, constant, @@ -38,13 +38,10 @@ use stackable_operator::{ }; use strum::{Display, EnumIter, EnumString}; -use crate::{ - crd::{ - authorization::KafkaAuthorization, - role::{KafkaRole, broker::BrokerConfigFragment, controller::ControllerConfigFragment}, - tls::KafkaTls, - }, - framework::commons::platform_access::tls::TlsClientCredential, +use crate::crd::{ + authorization::KafkaAuthorization, + role::{KafkaRole, broker::BrokerConfigFragment, controller::ControllerConfigFragment}, + tls::KafkaTls, }; pub const CONTAINER_IMAGE_BASE_NAME: &str = "kafka"; diff --git a/rust/operator-binary/src/framework/commons/mod.rs b/rust/operator-binary/src/framework/commons/mod.rs deleted file mode 100644 index ad8d7e6bd..000000000 --- a/rust/operator-binary/src/framework/commons/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod platform_access; diff --git a/rust/operator-binary/src/framework/commons/platform_access/mod.rs b/rust/operator-binary/src/framework/commons/platform_access/mod.rs deleted file mode 100644 index 7cedc76bf..000000000 --- a/rust/operator-binary/src/framework/commons/platform_access/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Credentials a product cluster grants the platform-access agent, and how to mount them. - -pub mod tls; diff --git a/rust/operator-binary/src/framework/commons/platform_access/tls.rs b/rust/operator-binary/src/framework/commons/platform_access/tls.rs deleted file mode 100644 index 592d1e51b..000000000 --- a/rust/operator-binary/src/framework/commons/platform_access/tls.rs +++ /dev/null @@ -1,87 +0,0 @@ -use serde::{Deserialize, Serialize}; -use stackable_operator::{ - builder::pod::{ - PodBuilder, - container::ContainerBuilder, - volume::{ - SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder, VolumeMountBuilder, - }, - }, - commons::secret_class::SecretClassVolumeProvisionParts, - k8s_openapi::api::core::v1::{SecretVolumeSource, Volume, VolumeMount}, - schemars::{self, JsonSchema}, - v2::types::kubernetes::{SecretClassName, SecretName}, -}; - -use crate::framework::constants::secret::SECRET_BASE_PATH; - -/// Source of a TLS client certificate: a secret-operator SecretClass or a static Secret. -#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub enum TlsClientCredential { - /// An AutoTLS SecretClass used to provision the certificate. - SecretClass(SecretClassName), - - /// A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), such as a - /// Secret of type `kubernetes.io/tls`. - Secret(SecretName), -} - -impl TlsClientCredential { - /// Adds the certificate volume to the Pod and mounts it into all given containers. - pub fn add_volumes_and_mounts( - &self, - pod_builder: &mut PodBuilder, - container_builders: Vec<&mut ContainerBuilder>, - ) { - let (volumes, mounts) = self.volumes_and_mounts(); - pod_builder - .add_volumes(volumes) - .expect("The volume name is derived from the credential and should not collide."); - for container_builder in container_builders { - container_builder - .add_volume_mounts(mounts.clone()) - .expect("The mount path is derived from the credential and should not collide."); - } - } - - fn volumes_and_mounts(&self) -> (Vec, Vec) { - let volume_name = self.volume_name(); - let volume = match self { - Self::SecretClass(secret_class) => VolumeBuilder::new(&volume_name) - .ephemeral( - SecretOperatorVolumeSourceBuilder::new( - secret_class, - SecretClassVolumeProvisionParts::PublicPrivate, - ) - .with_pod_scope() - .with_format(SecretFormat::TlsPem) - .build() - .expect("the annotations are built from a valid SecretClass name"), - ) - .build(), - Self::Secret(secret) => Volume { - name: volume_name.clone(), - secret: Some(SecretVolumeSource { - secret_name: Some(secret.to_string()), - ..SecretVolumeSource::default() - }), - ..Volume::default() - }, - }; - let mount = VolumeMountBuilder::new(&volume_name, self.mount_path()).build(); - (vec![volume], vec![mount]) - } - - /// The directory containing `tls.crt`, `tls.key` and `ca.crt` (PEM). - pub fn mount_path(&self) -> String { - format!("{SECRET_BASE_PATH}/{}", self.volume_name()) - } - - fn volume_name(&self) -> String { - match self { - Self::SecretClass(secret_class) => format!("{secret_class}-tls-cert"), - Self::Secret(secret) => format!("{secret}-tls-cert"), - } - } -} diff --git a/rust/operator-binary/src/framework/constants/mod.rs b/rust/operator-binary/src/framework/constants/mod.rs deleted file mode 100644 index 73b12dbbd..000000000 --- a/rust/operator-binary/src/framework/constants/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod secret; diff --git a/rust/operator-binary/src/framework/constants/secret.rs b/rust/operator-binary/src/framework/constants/secret.rs deleted file mode 100644 index 320faf979..000000000 --- a/rust/operator-binary/src/framework/constants/secret.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Mirrors the crate-private `SECRET_BASE_PATH` of operator-rs. -pub(crate) const SECRET_BASE_PATH: &str = "/stackable/secrets"; diff --git a/rust/operator-binary/src/framework/kvp/label.rs b/rust/operator-binary/src/framework/kvp/label.rs deleted file mode 100644 index f3695b8c7..000000000 --- a/rust/operator-binary/src/framework/kvp/label.rs +++ /dev/null @@ -1,45 +0,0 @@ -use stackable_operator::{ - kvp::{Label, Labels}, - v2::{ - kvp::label::{ - label_app_kubernetes_io_instance, label_app_kubernetes_io_managed_by, - label_app_kubernetes_io_name, label_app_kubernetes_io_version, - label_stackable_tech_vendor, - }, - types::operator::{ClusterName, ControllerName, OperatorName, ProductName, ProductVersion}, - }, -}; - -/// Creates the recommended labels for agent resources, like the agent Deployment. -pub fn recommended_labels_for_agent_resources( - cluster_name: &ClusterName, - product_name: &ProductName, - product_version: &ProductVersion, - operator_name: &OperatorName, - controller_name: &ControllerName, -) -> Labels { - Labels::from_iter([ - label_app_kubernetes_io_instance(cluster_name), - label_app_kubernetes_io_name(product_name), - label_app_kubernetes_io_version(product_version), - label_app_kubernetes_io_component_agent(), - label_app_kubernetes_io_managed_by(operator_name, controller_name), - label_stackable_tech_vendor(), - ]) -} - -/// Creates the agent selector. -/// -/// The returned labels are a subset of the recommended labels for agent resources. -pub fn agent_selector(cluster_name: &ClusterName, product_name: &ProductName) -> Labels { - Labels::from_iter([ - label_app_kubernetes_io_instance(cluster_name), - label_app_kubernetes_io_name(product_name), - label_app_kubernetes_io_component_agent(), - ]) -} - -/// Creates the `app.kubernetes.io/component` label with the value `agent`. -pub fn label_app_kubernetes_io_component_agent() -> Label { - Label::component("agent").expect("\"agent\" is a valid label value") -} diff --git a/rust/operator-binary/src/framework/kvp/mod.rs b/rust/operator-binary/src/framework/kvp/mod.rs deleted file mode 100644 index 0006163a0..000000000 --- a/rust/operator-binary/src/framework/kvp/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod label; diff --git a/rust/operator-binary/src/framework/mod.rs b/rust/operator-binary/src/framework/mod.rs deleted file mode 100644 index 842c16dde..000000000 --- a/rust/operator-binary/src/framework/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Product-agnostic building blocks, staged here until they move to operator-rs. The module paths -//! mirror operator-rs, so moving code there only changes imports. - -pub mod commons; -pub mod constants; -pub mod kvp; diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 941f4aa1e..809bd5664 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -43,7 +43,6 @@ use crate::{ mod controller; mod crd; -mod framework; mod webhooks; mod built_info { @@ -223,7 +222,7 @@ async fn main() -> anyhow::Result<()> { .map(anyhow::Ok); let delayed_kafka_controller = async { - signal::crd_established(&client, v1alpha1::KafkaCluster::crd_name(), None).await?; + signal::crd_established(&client, v1alpha1::KafkaCluster::crd_name()).await?; kafka_controller.await }; diff --git a/rust/operator-binary/src/webhooks/conversion.rs b/rust/operator-binary/src/webhooks/conversion.rs index 912ea5936..232e4dac4 100644 --- a/rust/operator-binary/src/webhooks/conversion.rs +++ b/rust/operator-binary/src/webhooks/conversion.rs @@ -4,6 +4,7 @@ use stackable_operator::{ kube::{Client, core::crd::MergeError}, webhook::{ WebhookServer, WebhookServerError, WebhookServerOptions, + health::HealthCheckRegistry, webhooks::{ConversionWebhook, ConversionWebhookOptions}, }, }; @@ -46,7 +47,11 @@ pub async fn create_webhook_server( webhook_service_name: operator_environment.operator_service_name.to_owned(), }; - WebhookServer::new(vec![Box::new(conversion_webhook)], webhook_server_options) - .await - .context(CreateWebhookSnafu) + WebhookServer::new( + vec![Box::new(conversion_webhook)], + webhook_server_options, + HealthCheckRegistry::new(), + ) + .await + .context(CreateWebhookSnafu) } From 7f6d5a1d9b897b556b98c0bfdb9e7ca1c67415b0 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Fri, 2 Oct 2026 15:47:43 +0200 Subject: [PATCH 07/25] fix issues identified by Claude --- Cargo.lock | 18 +++++----- Cargo.nix | 18 +++++----- .../kafka-operator/templates/_helpers.tpl | 10 +++++- .../templates/clusterrole-agent.yaml | 2 +- .../templates/clusterrole-operator.yaml | 2 +- .../src/controller/build/resource/agent.rs | 33 ++++++++++++++++--- 6 files changed, 57 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77847b010..9842b5ab4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1698,7 +1698,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "darling 0.24.1", "regex", @@ -3144,7 +3144,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "const-oid", "ecdsa", @@ -3202,7 +3202,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.119.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "base64 0.23.1", "clap", @@ -3246,7 +3246,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3257,7 +3257,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "jiff", "k8s-openapi", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "axum", "clap", @@ -3298,7 +3298,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "kube", "schemars", @@ -3312,7 +3312,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "convert_case", "darling 0.24.1", @@ -3329,7 +3329,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#7cb677e73bd218bcafb4ed4d4b459dda319fcbac" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 0f1de0737..b76c6a054 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5385,7 +5385,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -10303,7 +10303,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10546,7 +10546,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10745,7 +10745,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10780,7 +10780,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10861,7 +10861,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -10971,7 +10971,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11021,7 +11021,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11085,7 +11085,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "7cb677e73bd218bcafb4ed4d4b459dda319fcbac"; + rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; diff --git a/deploy/helm/kafka-operator/templates/_helpers.tpl b/deploy/helm/kafka-operator/templates/_helpers.tpl index 27536afa2..281aa5495 100644 --- a/deploy/helm/kafka-operator/templates/_helpers.tpl +++ b/deploy/helm/kafka-operator/templates/_helpers.tpl @@ -5,6 +5,14 @@ Expand the name of the chart. {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-operator" }} {{- end }} +{{/* +Fixed product name. Unlike kafka-operator.name it ignores nameOverride, because it must match +names hardcoded in the operator and the published image names. +*/}} +{{- define "kafka-operator.productName" -}} +kafka +{{- end }} + {{/* Expand the name of the chart. */}} @@ -89,5 +97,5 @@ Build the full operator container image reference. Build the full agent container image reference. The agent is released together with the operator. */}} {{- define "kafka-operator.agentImage" -}} -{{- printf "%s/%s-agent:%s" .Values.image.repository (include "kafka-operator.name" .) (.Values.image.tag | default .Chart.AppVersion) -}} +{{- printf "%s/%s-agent:%s" .Values.image.repository (include "kafka-operator.productName" .) (.Values.image.tag | default .Chart.AppVersion) -}} {{- end }} diff --git a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml index 8288ab33a..a17015062 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml @@ -4,7 +4,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: {{ include "kafka-operator.name" . }}-agent-clusterrole + name: {{ include "kafka-operator.productName" . }}-agent-clusterrole labels: {{- include "kafka-operator.labels" . | nindent 4 }} rules: diff --git a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml index 96045367c..cabc631e4 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml @@ -50,7 +50,7 @@ rules: - bind resourceNames: - {{ include "kafka-operator.name" . }}-clusterrole - - {{ include "kafka-operator.name" . }}-agent-clusterrole + - {{ include "kafka-operator.productName" . }}-agent-clusterrole # StatefulSet created per role group (broker, KRaft controller). Applied via # SSA, tracked for orphan cleanup, and owned by the controller. - apiGroups: diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index e466512fd..35db34806 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -82,6 +82,7 @@ pub fn build_agent_deployment( .with_labels(recommended_labels_for_agent_resources(cluster)) .build(), ) + .image_pull_secrets_from_product_image(&cluster.image) .add_container(cb_agent.build()) .service_account_name(agent_name(cluster)) .security_context(PodSecurityContextBuilder::with_stackable_defaults().build()); @@ -152,6 +153,10 @@ mod tests { }; fn cluster(platform_access: &str) -> ValidatedCluster { + cluster_with_image("{productVersion: 3.9.2}", platform_access) + } + + fn cluster_with_image(image: &str, platform_access: &str) -> ValidatedCluster { let kafka = minimal_kafka(&format!( r#" apiVersion: kafka.stackable.tech/v1alpha1 @@ -161,8 +166,7 @@ mod tests { namespace: default uid: 12345678-1234-1234-1234-123456789012 spec: - image: - productVersion: 3.9.2 + image: {image} clusterConfig: zookeeperConfigMapName: xyz platformAccess: {platform_access} @@ -235,9 +239,9 @@ mod tests { assert_eq!(pod_spec["containers"][0]["args"], json!(["run"])); assert_eq!( pod_spec["containers"][0]["volumeMounts"], - json!([{"mountPath": "/stackable/secrets/tls-tls-cert", "name": "tls-tls-cert"}]) + json!([{"mountPath": "/stackable/secrets/tls-client-cert", "name": "tls-client-cert"}]) ); - assert_eq!(pod_spec["volumes"][0]["name"], "tls-tls-cert"); + assert_eq!(pod_spec["volumes"][0]["name"], "tls-client-cert"); assert_eq!( pod_spec["volumes"][0]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"]["secrets.stackable.tech/class"], "tls" @@ -251,7 +255,26 @@ mod tests { assert_eq!( deployment["spec"]["template"]["spec"]["volumes"], - json!([{"name": "my-cert-tls-cert", "secret": {"secretName": "my-cert"}}]) + json!([{"name": "tls-client-cert", "secret": {"secretName": "my-cert"}}]) + ); + } + + #[test] + fn test_deployment_uses_product_image_pull_secrets() { + let cluster = cluster_with_image( + "{productVersion: 3.9.2, pullSecrets: [{name: regcred}]}", + "{enabled: true, authentication: {tls: {secretClass: tls}}}", + ); + let agent_config = cluster + .agent_config + .as_ref() + .expect("platform access is enabled"); + let deployment = serde_json::to_value(build_agent_deployment(&cluster, agent_config)) + .expect("must be serializable"); + + assert_eq!( + deployment["spec"]["template"]["spec"]["imagePullSecrets"], + json!([{"name": "regcred"}]) ); } From e5f431bea08f83527a1d082aec51ed5658823ddd Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 6 Oct 2026 15:13:35 +0200 Subject: [PATCH 08/25] add support for anonymous access via operator-rs --- Cargo.lock | 373 +++++++------ Cargo.nix | 523 ++++++++++-------- extra/crds.yaml | 7 +- .../src/controller/build/resource/agent.rs | 10 + rust/operator-binary/src/crd/mod.rs | 9 +- 5 files changed, 528 insertions(+), 394 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9842b5ab4..da8c1babd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,7 +169,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -279,9 +279,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "block-buffer" @@ -316,9 +316,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.4.4" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630" dependencies = [ "find-msvc-tools", "jobserver", @@ -328,9 +328,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "chacha20" @@ -339,7 +339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures 0.3.1", "rand_core 0.10.1", ] @@ -356,9 +356,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -366,9 +366,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -378,21 +378,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.4" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] name = "clap_lex" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" [[package]] name = "colorchoice" @@ -402,9 +402,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" -version = "4.6.7" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", "memchr", @@ -462,6 +462,12 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -473,36 +479,36 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-bigint" @@ -569,7 +575,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -591,7 +597,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core 0.24.1", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -622,7 +628,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -707,7 +713,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -771,7 +777,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -802,11 +808,16 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.35" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679" dependencies = [ "cfg-if", + "core_detect", + "multiversion_no_op", + "rustversion", + "scopeguard", + "simdutf8", ] [[package]] @@ -844,7 +855,7 @@ checksum = "a65863d15a4ce2888bd2f0f543cc963d3879c3a022c8ee43f6141d479a3ac815" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -901,9 +912,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "flagset" @@ -913,12 +924,13 @@ checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -998,7 +1010,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -1090,7 +1102,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "libc", "libgit2-sys", "log", @@ -1137,9 +1149,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839c0e8a181239723652be9062bb56ca5bf5f64011f73b623f6f4fc59086a228" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", @@ -1250,9 +1262,9 @@ checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hyper" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", @@ -1272,9 +1284,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.9" +version = "0.27.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" dependencies = [ "http", "hyper", @@ -1302,16 +1314,17 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-channel", "futures-util", "http", "http-body", + "httparse", "hyper", "ipnet", "libc", @@ -1459,9 +1472,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -1478,9 +1491,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" [[package]] name = "is_terminal_polyfill" @@ -1525,9 +1538,9 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" dependencies = [ "defmt", "jiff-core", @@ -1542,18 +1555,19 @@ dependencies = [ [[package]] name = "jiff-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" dependencies = [ "defmt", + "log", ] [[package]] name = "jiff-static" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" dependencies = [ "jiff-core", "proc-macro2", @@ -1588,7 +1602,7 @@ dependencies = [ "jni-sys", "log", "simd_cesu8", - "thiserror 2.0.20", + "thiserror 2.0.21", "walkdir", "windows-link", ] @@ -1637,9 +1651,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -1656,20 +1670,20 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] name = "jsonpath-rust" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e07021eefc09f897611b067ba7897b5e9266edfc902768418968772e5bb06a7" +checksum = "d23892d4caa103325a558250e9f4e406d81cf64f7c01679ae7a64e0413321e51" dependencies = [ "pest", "pest_derive", "regex", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -1698,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "darling 0.24.1", "regex", @@ -1761,7 +1775,7 @@ dependencies = [ "serde", "serde-saphyr", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tokio-util", "tower", @@ -1785,7 +1799,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -1823,7 +1837,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tokio-util", "tracing", @@ -1831,18 +1845,18 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" dependencies = [ "spin", ] [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libgit2-sys" @@ -1924,9 +1938,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" dependencies = [ "adler2", "simd-adler32", @@ -1934,15 +1948,21 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "wasi", "windows-sys 0.61.2", ] +[[package]] +name = "multiversion_no_op" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2037,7 +2057,7 @@ dependencies = [ "futures-sink", "js-sys", "pin-project-lite", - "thiserror 2.0.20", + "thiserror 2.0.21", "tracing", ] @@ -2080,7 +2100,7 @@ dependencies = [ "opentelemetry_sdk", "prost", "reqwest", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tonic", "tonic-types", @@ -2118,7 +2138,7 @@ dependencies = [ "percent-encoding", "portable-atomic", "rand 0.9.5", - "thiserror 2.0.20", + "thiserror 2.0.21", "tokio", "tokio-stream", ] @@ -2200,9 +2220,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf" +checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8" dependencies = [ "memchr", "ucd-trie", @@ -2210,9 +2230,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d" +checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf" dependencies = [ "pest", "pest_generator", @@ -2220,9 +2240,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a" +checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109" dependencies = [ "pest", "pest_meta", @@ -2233,9 +2253,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496" +checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb" dependencies = [ "pest", ] @@ -2301,9 +2321,9 @@ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" dependencies = [ "portable-atomic", ] @@ -2319,9 +2339,9 @@ dependencies = [ [[package]] name = "powerfmt" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958" [[package]] name = "ppv-lite86" @@ -2434,9 +2454,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom 0.4.3", @@ -2493,7 +2513,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", ] [[package]] @@ -2513,7 +2533,7 @@ checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -2553,11 +2573,11 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-channel", "futures-core", @@ -2703,9 +2723,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" dependencies = [ "core-foundation", "core-foundation-sys", @@ -2724,9 +2744,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier-android" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" +checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" [[package]] name = "rustls-webpki" @@ -2792,7 +2812,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -2830,7 +2850,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "core-foundation", "core-foundation-sys", "libc", @@ -2913,7 +2933,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -2924,7 +2944,7 @@ checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -3144,14 +3164,14 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "const-oid", "ecdsa", "k8s-openapi", "kube", "p256", - "rand 0.10.2", + "rand 0.10.3", "rand_core 0.6.4", "rsa", "sha2", @@ -3202,7 +3222,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.119.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "base64 0.23.1", "clap", @@ -3219,7 +3239,7 @@ dependencies = [ "json-patch", "k8s-openapi", "kube", - "rand 0.10.2", + "rand 0.10.3", "regex", "schemars", "semver", @@ -3246,18 +3266,18 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "darling 0.24.1", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] name = "stackable-shared" version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "jiff", "k8s-openapi", @@ -3274,7 +3294,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "axum", "clap", @@ -3298,7 +3318,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "kube", "schemars", @@ -3312,7 +3332,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "convert_case", "darling 0.24.1", @@ -3323,13 +3343,13 @@ dependencies = [ "kube", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#f3d2da737aa49086cbdaba806aaf2c8645251cfb" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" dependencies = [ "arc-swap", "async-trait", @@ -3342,7 +3362,7 @@ dependencies = [ "kube", "opentelemetry", "opentelemetry-semantic-conventions", - "rand 0.10.2", + "rand 0.10.3", "serde", "serde_json", "snafu 0.9.2", @@ -3421,9 +3441,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -3441,13 +3461,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] @@ -3461,11 +3481,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.21", ] [[package]] @@ -3481,13 +3501,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] @@ -3562,9 +3582,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" dependencies = [ "bytes", "libc", @@ -3585,14 +3605,14 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] [[package]] name = "tokio-rustls" -version = "0.26.4" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" dependencies = [ "rustls", "tokio", @@ -3635,9 +3655,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.15+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" dependencies = [ "indexmap", "toml_datetime", @@ -3729,7 +3749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.13.2", "bytes", "futures-util", "http", @@ -3749,7 +3769,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08a05a66a4fdd61cbbe0a1d755ffe0ca6aba159dd4820936a0ff8a8278245b9c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.13.2", "bytes", "http", "http-body", @@ -3792,7 +3812,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.20", + "thiserror 2.0.21", "time", "tracing-subscriber", ] @@ -3896,9 +3916,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "unicode-segmentation" @@ -3957,9 +3977,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.25.0" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc" +checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a" dependencies = [ "js-sys", "wasm-bindgen", @@ -3995,9 +4015,9 @@ dependencies = [ [[package]] name = "want" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" dependencies = [ "try-lock", ] @@ -4019,9 +4039,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -4032,19 +4052,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" dependencies = [ "js-sys", + "tokio", "wasm-bindgen", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4052,31 +4073,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" dependencies = [ "js-sys", "wasm-bindgen", @@ -4305,30 +4326,30 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "6400fc4bb7426f6faac3fb07566122bb18622e3022bd2c36426a92ed489b1dbe" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "99c27cc7525bad4df59a45e073c45b2c2aa820efb588234cc23a547ec69a34db" dependencies = [ "proc-macro2", "quote", @@ -4346,13 +4367,13 @@ dependencies = [ [[package]] name = "zerofrom-derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] @@ -4406,9 +4427,15 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.6", ] +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + [[package]] name = "zmij" version = "1.0.23" diff --git a/Cargo.nix b/Cargo.nix index b76c6a054..17baabbeb 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -506,7 +506,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; usesDefaultFeatures = false; features = [ "clone-impls" "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } @@ -889,11 +889,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.13.1" = rec { + "bitflags 2.13.2" = rec { crateName = "bitflags"; - version = "2.13.1"; + version = "2.13.2"; edition = "2021"; - sha256 = "1nl76mpykmwmb8rq1l5vw1azdh1wvxdrnsk4sy3rdrzx01nvg25m"; + sha256 = "01hbgjwvid66850fzi76mvn5f2bqycx6sf165ng1kfjqq9bl1v9x"; authors = [ "The Rust Project Developers" ]; @@ -987,9 +987,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.4.4"; + version = "1.6.0"; edition = "2021"; - sha256 = "0wq26vvhzv5ci9gx3cfiw320skvaysf9i701wp668lks6ps39m8a"; + sha256 = "0c3n82hdi355xa6z9x4zgnpjwsh1szkkcs0zl8q8nl5ggk874j7p"; dependencies = [ { name = "find-msvc-tools"; @@ -1020,9 +1020,9 @@ rec { }; "cfg-if" = rec { crateName = "cfg-if"; - version = "1.0.4"; + version = "1.0.5"; edition = "2018"; - sha256 = "008q28ajc546z5p2hcwdnckmg0hia7rnx52fni04bwqkzyrghc4k"; + sha256 = "0026j56901nzjraap3da0a8njw42j66zcxnn6s2s9aa5bcblhxjf"; libName = "cfg_if"; authors = [ "Alex Crichton " @@ -1047,7 +1047,7 @@ rec { } { name = "cpufeatures"; - packageId = "cpufeatures 0.3.0"; + packageId = "cpufeatures 0.3.1"; target = { target, features }: (("x86_64" == target."arch" or null) || ("x86" == target."arch" or null)); } { @@ -1118,10 +1118,10 @@ rec { }; "clap" = rec { crateName = "clap"; - version = "4.6.6"; + version = "4.6.7"; edition = "2024"; crateBin = []; - sha256 = "1jmx5z8d6jbvxdz6dybh599s4rd7ns6sl90p2rrdga09yh3pwg27"; + sha256 = "0il98y2rfw75984ck59znd4n592p07bxz8yy3a9blddb02rpd25a"; dependencies = [ { name = "clap_builder"; @@ -1160,9 +1160,9 @@ rec { }; "clap_builder" = rec { crateName = "clap_builder"; - version = "4.6.6"; + version = "4.6.7"; edition = "2024"; - sha256 = "12cqg25zpjc3k82cpqa2v9h7s3vk1vydpgnwl8lfg6lfm2jzwj3v"; + sha256 = "0kbhai5rv1vj9r4np52g2b9fmhvy3y82digs9v40c57bgbxrf1zc"; dependencies = [ { name = "anstream"; @@ -1199,9 +1199,9 @@ rec { }; "clap_derive" = rec { crateName = "clap_derive"; - version = "4.6.4"; + version = "4.6.7"; edition = "2024"; - sha256 = "0qd0v7pa2arwxjjinmjim6xrjy61bc28m1yryhc7zjjssswx44nh"; + sha256 = "1q36bgbkfb9rdz7jcvd0ffv0wwlyw0lg3z6iwdcybm0mjjvm3izr"; procMacro = true; dependencies = [ { @@ -1218,7 +1218,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "full" ]; } ]; @@ -1231,9 +1231,9 @@ rec { }; "clap_lex" = rec { crateName = "clap_lex"; - version = "1.1.0"; + version = "1.1.1"; edition = "2024"; - sha256 = "1ycqkpygnlqnndghhcxjb44lzl0nmgsia64x9581030yifxs7m68"; + sha256 = "11k4m4ngn39iz39lnq6nn6kyxzp62mnm1d86qfad3q0vlk33n4qw"; }; "colorchoice" = rec { @@ -1245,9 +1245,9 @@ rec { }; "combine" = rec { crateName = "combine"; - version = "4.6.7"; + version = "4.6.8"; edition = "2018"; - sha256 = "1z8rh8wp59gf8k23ar010phgs0wgf5i8cx4fg01gwcnzfn5k0nms"; + sha256 = "0ppwzwdmszpan9ybx1myc6ldg5zih2sazf9idckdxrh9gn9j1hyg"; authors = [ "Markus Westerlind " ]; @@ -1433,6 +1433,18 @@ rec { }; resolvedDefaultFeatures = [ "default" "link" ]; }; + "core_detect" = rec { + crateName = "core_detect"; + version = "1.0.0"; + edition = "2018"; + sha256 = "0j0xp1j6f9lrp4ybylc3d0zdg8jq2hkmr1122qyil14qk84q13vz"; + authors = [ + "Thom Chiovoloni " + ]; + features = { + }; + resolvedDefaultFeatures = [ "default" ]; + }; "cpufeatures 0.2.17" = rec { crateName = "cpufeatures"; version = "0.2.17"; @@ -1469,11 +1481,11 @@ rec { ]; }; - "cpufeatures 0.3.0" = rec { + "cpufeatures 0.3.1" = rec { crateName = "cpufeatures"; - version = "0.3.0"; + version = "0.3.1"; edition = "2024"; - sha256 = "00fjhygsqmh4kbxxlb99mcsbspxcai6hjydv4c46pwb67wwl2alb"; + sha256 = "0rkm1l35jy1z1yfg723fddsxc7vr0gc1hhfvc138hnqiwc58p8jw"; authors = [ "RustCrypto Developers" ]; @@ -1507,9 +1519,9 @@ rec { }; "crc32fast" = rec { crateName = "crc32fast"; - version = "1.5.1"; + version = "1.5.2"; edition = "2021"; - sha256 = "0l75bfakpwr86wz45gm38lylrpgbssr529fmm6m445qy2rqwi644"; + sha256 = "0y0f955n2hr5a8rd9nw9sr23nhjc42ddx3bjc47dnlmqssgpk9q1"; authors = [ "Sam Rijs " "Alex Crichton " @@ -1523,13 +1535,13 @@ rec { features = { "default" = [ "std" ]; }; - resolvedDefaultFeatures = [ "default" "std" ]; + resolvedDefaultFeatures = [ "std" ]; }; "crossbeam-channel" = rec { crateName = "crossbeam-channel"; - version = "0.5.16"; + version = "0.5.17"; edition = "2021"; - sha256 = "17k72dh5qqkh0xvqzr27wny7gl1l7fgzlvh2xxx71jmfgz1n6lyq"; + sha256 = "1wcy7y77hw7z5m140114iqxb90gsq062djd9zpkndisvgcrcrc4q"; libName = "crossbeam_channel"; dependencies = [ { @@ -1546,9 +1558,9 @@ rec { }; "crossbeam-utils" = rec { crateName = "crossbeam-utils"; - version = "0.8.22"; + version = "0.8.23"; edition = "2021"; - sha256 = "05vwf7pmjq8c8f3fp5qqdm0z3cnk4p62wi8spf0jms5yjnh3v031"; + sha256 = "1ilan2nw7fvka8hki80fr57a5dgd4mvcsvwq60437j6yvlwyw7m3"; libName = "crossbeam_utils"; features = { "default" = [ "std" ]; @@ -1753,7 +1765,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "full" "extra-traits" ]; } ]; @@ -1809,7 +1821,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; @@ -1882,7 +1894,7 @@ rec { dependencies = [ { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } ]; features = { @@ -2177,7 +2189,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; features = { @@ -2385,7 +2397,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "visit" "visit-mut" ]; } ]; @@ -2507,9 +2519,9 @@ rec { }; "encoding_rs" = rec { crateName = "encoding_rs"; - version = "0.8.35"; - edition = "2018"; - sha256 = "1wv64xdrr9v37rqqdjsyb8l8wzlcbab80ryxhrszvnj59wy0y0vm"; + version = "0.8.42"; + edition = "2024"; + sha256 = "0ycnbndly2jw5j69jl1r1lm512h2w9vb1dnjp0px46l7a425x64f"; authors = [ "Henri Sivonen " ]; @@ -2518,13 +2530,47 @@ rec { name = "cfg-if"; packageId = "cfg-if"; } + { + name = "core_detect"; + packageId = "core_detect"; + target = { target, features }: (("x86_64" == target."arch" or null) || ("x86" == target."arch" or null)); + } + { + name = "multiversion_no_op"; + packageId = "multiversion_no_op"; + } + { + name = "rustversion"; + packageId = "rustversion"; + optional = true; + } + { + name = "scopeguard"; + packageId = "scopeguard"; + usesDefaultFeatures = false; + } + { + name = "simdutf8"; + packageId = "simdutf8"; + usesDefaultFeatures = false; + target = { target, features }: (("x86_64" == target."arch" or null) || ("x86" == target."arch" or null) || ("aarch64" == target."arch" or null) || (("wasm32" == target."arch" or null) && (builtins.elem "simd128" targetFeatures))); + features = [ "aarch64_neon" "public_imp" ]; + } + ]; + buildDependencies = [ + { + name = "rustversion"; + packageId = "rustversion"; + } ]; features = { "any_all_workaround" = [ "dep:any_all_workaround" ]; "default" = [ "alloc" ]; "fast-legacy-encode" = [ "fast-hangul-encode" "fast-hanja-encode" "fast-kanji-encode" "fast-gb-hanzi-encode" "fast-big5-hanzi-encode" ]; + "rustversion" = [ "dep:rustversion" ]; "serde" = [ "dep:serde" ]; - "simd-accel" = [ "any_all_workaround" ]; + "simd-accel" = [ "any_all_workaround" "rustversion" ]; + "std" = [ "dep:multiversion" ]; }; resolvedDefaultFeatures = [ "alloc" "default" ]; }; @@ -2599,7 +2645,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; features = { @@ -2767,9 +2813,9 @@ rec { }; "find-msvc-tools" = rec { crateName = "find-msvc-tools"; - version = "0.1.11"; + version = "0.1.14"; edition = "2021"; - sha256 = "145qpfb9r4ml2klr8v4byvrkikp61qyiks9n69b8z0vbscbb0pfl"; + sha256 = "112ljldlv150fpl8xr2jl5czg51k3kdfn6cy5fqdsvkl14sgpp5f"; libName = "find_msvc_tools"; }; @@ -2787,9 +2833,9 @@ rec { }; "flate2" = rec { crateName = "flate2"; - version = "1.1.9"; + version = "1.1.10"; edition = "2018"; - sha256 = "0g2pb7cxnzcbzrj8bw4v6gpqqp21aycmf6d84rzb6j748qkvlgw4"; + sha256 = "1jvd2cl8j5hyf8imi62y1x7gwzz1hajirni0801yxhds1qp4wqvf"; authors = [ "Alex Crichton " "Josh Triplett " @@ -2799,33 +2845,33 @@ rec { name = "crc32fast"; packageId = "crc32fast"; optional = true; + usesDefaultFeatures = false; } { name = "miniz_oxide"; packageId = "miniz_oxide"; optional = true; - usesDefaultFeatures = false; - features = [ "with-alloc" "simd" ]; + features = [ "simd" ]; } { - name = "miniz_oxide"; - packageId = "miniz_oxide"; + name = "zlib-rs"; + packageId = "zlib-rs"; + optional = true; usesDefaultFeatures = false; - target = { target, features }: (("wasm32" == target."arch" or null) && (!("emscripten" == target."os" or null))); - features = [ "with-alloc" "simd" ]; + features = [ "rust-allocator" ]; } ]; features = { "any_c_zlib" = [ "any_zlib" ]; "any_zlib" = [ "any_impl" ]; - "cloudflare-zlib-sys" = [ "dep:cloudflare-zlib-sys" ]; - "cloudflare_zlib" = [ "any_c_zlib" "cloudflare-zlib-sys" "dep:crc32fast" ]; - "default" = [ "rust_backend" ]; + "cloudflare_zlib" = [ "zlib" ]; + "default" = [ "rust_backend" "runtime_detection" ]; "document-features" = [ "dep:document-features" ]; "libz-ng-sys" = [ "dep:libz-ng-sys" ]; "libz-sys" = [ "dep:libz-sys" ]; "miniz-sys" = [ "rust_backend" ]; "miniz_oxide" = [ "any_impl" "dep:miniz_oxide" "dep:crc32fast" ]; + "runtime_detection" = [ "zlib-rs?/std" "crc32fast?/std" ]; "rust_backend" = [ "miniz_oxide" "any_impl" ]; "zlib" = [ "any_c_zlib" "libz-sys" "dep:crc32fast" ]; "zlib-default" = [ "any_c_zlib" "libz-sys/default" "dep:crc32fast" ]; @@ -2833,7 +2879,7 @@ rec { "zlib-ng-compat" = [ "zlib" "libz-sys/zlib-ng" "dep:crc32fast" ]; "zlib-rs" = [ "any_zlib" "dep:zlib-rs" ]; }; - resolvedDefaultFeatures = [ "any_impl" "default" "miniz_oxide" "rust_backend" ]; + resolvedDefaultFeatures = [ "any_impl" "default" "miniz_oxide" "runtime_detection" "rust_backend" ]; }; "fnv" = rec { crateName = "fnv"; @@ -3045,7 +3091,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "full" ]; } ]; @@ -3432,7 +3478,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.13.1"; + packageId = "bitflags 2.13.2"; } { name = "libc"; @@ -3570,9 +3616,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.4.18"; + version = "0.4.19"; edition = "2021"; - sha256 = "0a52hs8cakvg7xi3pxqi83vganyaasxn545ya8v74f8j3250x743"; + sha256 = "05mw60jmsq97vjgj607nxjkx8dl6rxv6jj9i4r2z92056id5x3pg"; authors = [ "Carl Lerche " "Sean McArthur " @@ -3881,9 +3927,9 @@ rec { }; "hyper" = rec { crateName = "hyper"; - version = "1.11.0"; + version = "1.11.1"; edition = "2021"; - sha256 = "0wha96biivgpj0fpf80a2aar5dfbff1lk62i9x9i2bl53wl5686j"; + sha256 = "0hxyikj5livhmw5q3x3ifyhphh1g2cjsc32nsg1jcyhflpx03d97"; authors = [ "Sean McArthur " ]; @@ -3986,9 +4032,9 @@ rec { }; "hyper-rustls" = rec { crateName = "hyper-rustls"; - version = "0.27.9"; + version = "0.27.10"; edition = "2021"; - sha256 = "03vfnsm873wsp1dk0q85nxvk7w6syp8c2m5bcdjcyfgg4786ijik"; + sha256 = "0lvz2bxpphyxmkws5ysfnydvsd0q4smbwgy254g92irjf1afda6z"; libName = "hyper_rustls"; dependencies = [ { @@ -4125,9 +4171,9 @@ rec { }; "hyper-util" = rec { crateName = "hyper-util"; - version = "0.1.20"; - edition = "2021"; - sha256 = "186zdc58hmm663csmjvrzgkr6jdh93sfmi3q2pxi57gcaqjpqm4n"; + version = "0.1.21"; + edition = "2024"; + sha256 = "1zwbrhqr9js6r7db3zd8bsmm6ys1i0abgkc7lyw2d4jgd2b3vh6x"; libName = "hyper_util"; authors = [ "Sean McArthur " @@ -4135,7 +4181,7 @@ rec { dependencies = [ { name = "base64"; - packageId = "base64 0.22.1"; + packageId = "base64 0.23.1"; optional = true; } { @@ -4161,6 +4207,11 @@ rec { name = "http-body"; packageId = "http-body"; } + { + name = "httparse"; + packageId = "httparse"; + optional = true; + } { name = "hyper"; packageId = "hyper"; @@ -4228,18 +4279,19 @@ rec { { name = "tokio"; packageId = "tokio"; - features = [ "macros" "test-util" "signal" ]; + features = [ "macros" "test-util" "signal" "net" "io-util" ]; } ]; features = { - "client" = [ "hyper/client" "tokio/net" "dep:tracing" "dep:futures-channel" "dep:tower-service" ]; - "client-legacy" = [ "client" "dep:socket2" "tokio/sync" "dep:libc" "dep:futures-util" ]; - "client-pool" = [ "client" "dep:futures-util" "dep:tower-layer" ]; + "client" = [ "hyper/client" "dep:tracing" "dep:futures-channel" "dep:tower-service" ]; + "client-legacy" = [ "client" "tokio/net" "dep:socket2" "tokio/sync" "dep:libc" "dep:futures-util" "dep:httparse" ]; + "client-pool" = [ "client" "dep:futures-util" "dep:tower-layer" "tokio/sync" ]; "client-proxy" = [ "client" "dep:base64" "dep:ipnet" "dep:percent-encoding" ]; "client-proxy-system" = [ "dep:system-configuration" "dep:windows-registry" ]; "full" = [ "client" "client-legacy" "client-pool" "client-proxy" "client-proxy-system" "server" "server-auto" "server-graceful" "service" "http1" "http2" "tokio" "tracing" ]; "http1" = [ "hyper/http1" ]; "http2" = [ "hyper/http2" ]; + "rt-tracing-exec-force" = [ "tokio" "tracing" ]; "server" = [ "hyper/server" ]; "server-auto" = [ "server" "http1" "http2" ]; "server-graceful" = [ "server" "tokio/sync" ]; @@ -4685,9 +4737,9 @@ rec { }; "indexmap" = rec { crateName = "indexmap"; - version = "2.14.0"; + version = "2.14.2"; edition = "2024"; - sha256 = "1na9z6f0d5pkjr1lgsni470v98gv2r7c41j8w48skr089x2yjrnl"; + sha256 = "0mf86hbjkkcd82cpq683bblbs0zwa8ndla96ci8p1ji6bl7ijknc"; dependencies = [ { name = "equivalent"; @@ -4736,9 +4788,9 @@ rec { }; "ipnet" = rec { crateName = "ipnet"; - version = "2.12.1"; + version = "2.12.2"; edition = "2018"; - sha256 = "0y6xssyvfy85k90pnnanxv9phayxalhp8bacy61rw4vkmhznqxba"; + sha256 = "1h65hw16sqv8nrrmqp0g8drv5wh98n4z7a4h1lb76n8d7js306br"; authors = [ "Kris Price " ]; @@ -4844,9 +4896,9 @@ rec { }; "jiff" = rec { crateName = "jiff"; - version = "0.2.35"; + version = "0.2.37"; edition = "2021"; - sha256 = "1k1d1n8k46192xz6ph8km43lcg68ql65phzmhm49mbq7pn1p32v6"; + sha256 = "1nxgdj2wajw9ml8fcc2zq858k6v9618m22864vh6sy885zvvmc8a"; authors = [ "Andrew Gallant " ]; @@ -4917,6 +4969,7 @@ rec { ]; features = { "alloc" = [ "jcore/alloc" "serde_core?/alloc" "portable-atomic-util/alloc" "defmt?/alloc" ]; + "arbitrary" = [ "dep:arbitrary" "jcore/arbitrary" "std" ]; "default" = [ "std" "tz-system" "tz-fat" "tzdb-bundle-platform" "tzdb-zoneinfo" "tzdb-concatenated" "perf-inline" ]; "defmt" = [ "dep:defmt" "jcore/defmt" ]; "js" = [ "dep:wasm-bindgen" "dep:js-sys" ]; @@ -4936,9 +4989,9 @@ rec { }; "jiff-core" = rec { crateName = "jiff-core"; - version = "0.1.0"; + version = "0.1.1"; edition = "2021"; - sha256 = "02axx56pkh2w4bw5rp94qlvcpwzd3n2w2025fnikvrgg762aiv3z"; + sha256 = "130jqxlbrmll1ahvm9lwr06grmzpmnx5wc6j0n8crkiw0ivgwljy"; libName = "jiff_core"; authors = [ "Andrew Gallant " @@ -4949,21 +5002,28 @@ rec { packageId = "defmt"; optional = true; } + { + name = "log"; + packageId = "log"; + optional = true; + usesDefaultFeatures = false; + } ]; features = { "alloc" = [ "defmt?/alloc" ]; + "arbitrary" = [ "dep:arbitrary" "std" ]; "default" = [ "std" "tz-fat" ]; "defmt" = [ "dep:defmt" ]; "logging" = [ "dep:log" ]; - "std" = [ "alloc" ]; + "std" = [ "alloc" "log?/std" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "std" "tz-fat" ]; }; "jiff-static" = rec { crateName = "jiff-static"; - version = "0.2.35"; + version = "0.2.37"; edition = "2021"; - sha256 = "014jli8v46c8hzkndmvdfvq4la6a6y9icmnh3k735yqwlarxqs9s"; + sha256 = "04kjdzg4h4wy38ghm91qva7xg4glr65120c74bk7mmka26hni0ip"; procMacro = true; libName = "jiff_static"; authors = [ @@ -5058,7 +5118,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } { name = "windows-link"; @@ -5176,9 +5236,9 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.104"; + version = "0.3.106"; edition = "2021"; - sha256 = "0fjsgady7wbv7bbyy6c8qhrd93bnx11qbl83l1g7bb9a4601030f"; + sha256 = "1icwmpjw54lb7vg5926k5y4y5jbiih0zxhwgjwnzn475v90xk0vq"; libName = "js_sys"; authors = [ "The wasm-bindgen Developers" @@ -5193,7 +5253,6 @@ rec { packageId = "futures-util"; optional = true; usesDefaultFeatures = false; - features = [ "std" ]; } { name = "wasm-bindgen"; @@ -5204,7 +5263,7 @@ rec { features = { "default" = [ "std" "unsafe-eval" ]; "futures-core-03-stream" = [ "dep:futures-util" "dep:futures-core" ]; - "std" = [ "wasm-bindgen/std" "dep:futures-util" ]; + "std" = [ "wasm-bindgen/std" "futures-util/std" ]; }; resolvedDefaultFeatures = [ "default" "std" "unsafe-eval" ]; }; @@ -5238,7 +5297,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } ]; devDependencies = [ @@ -5261,9 +5320,9 @@ rec { }; "jsonpath-rust" = rec { crateName = "jsonpath-rust"; - version = "1.0.8"; + version = "1.0.11"; edition = "2021"; - sha256 = "19q6pgjp51wn3227c0n9vxp2dsdmjxwblrxh25v8k7y0xwg041rf"; + sha256 = "0l8y689h8km6wyd6f0bw9zv1rn06wksfjl42amd340x1rba94f6j"; libName = "jsonpath_rust"; authors = [ "BorisZhguchev " @@ -5287,7 +5346,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } ]; @@ -5385,7 +5444,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -5664,7 +5723,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } { name = "tokio"; @@ -5830,7 +5889,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } ]; devDependencies = [ @@ -5982,7 +6041,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } { name = "tokio"; @@ -6022,9 +6081,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.5.0"; + version = "1.5.1"; edition = "2015"; - sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; + sha256 = "1yqaqmp510xw2ldpw88mx9b5s5qj8flb4rw0wd9ks1zpk9j0z1r0"; authors = [ "Marvin Löbel " ]; @@ -6045,9 +6104,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.189"; + version = "0.2.190"; edition = "2021"; - sha256 = "1whjfs375vlng2q6yrbzs73cvp5lm3w1n2gfqajb2vgf7zg3xbry"; + sha256 = "0y5yap4bfp7rfsldcbk9pb5alcgygca5xn1n2pmh181zdpf3spff"; features = { "default" = [ "std" ]; "rustc-dep-of-std" = [ "align" "rustc-std-workspace-core" ]; @@ -6285,9 +6344,9 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.8.9"; + version = "0.9.1"; edition = "2021"; - sha256 = "05k3pdg8bjjzayq3rf0qhpirq9k37pxnasfn4arbs17phqn6m9qz"; + sha256 = "0k2bgjzk2sbsynpsv4wizwxbqp6vs7g08y5anbkrh3l6a15bqgxn"; authors = [ "Frommi " "oyvindln " @@ -6314,14 +6373,15 @@ rec { "serde" = [ "dep:serde" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; + "std" = [ "serde?/std" ]; }; - resolvedDefaultFeatures = [ "simd" "simd-adler32" "with-alloc" ]; + resolvedDefaultFeatures = [ "default" "simd" "simd-adler32" "with-alloc" ]; }; "mio" = rec { crateName = "mio"; - version = "1.2.2"; + version = "1.2.4"; edition = "2021"; - sha256 = "09y4b7gc42ymgssshh8sz6gs3y5r8bbigqaw2c4snh6fy5qmrmih"; + sha256 = "1vl6px9zy0pwhlwnw3cknsqyzkg8bcpiwiq4cgicf2fwgywfv20p"; authors = [ "Carl Lerche " "Thomas de Zeeuw " @@ -6352,6 +6412,17 @@ rec { }; resolvedDefaultFeatures = [ "net" "os-ext" "os-poll" ]; }; + "multiversion_no_op" = rec { + crateName = "multiversion_no_op"; + version = "1.0.0"; + edition = "2021"; + sha256 = "03d2k7xk7vky38q48h08miw4jca34ymckggnrqggn60vlddvagvl"; + procMacro = true; + authors = [ + "Henri Sivonen " + ]; + + }; "nohash-hasher" = rec { crateName = "nohash-hasher"; version = "0.2.0"; @@ -6626,7 +6697,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; optional = true; usesDefaultFeatures = false; } @@ -6800,7 +6871,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; usesDefaultFeatures = false; } { @@ -7004,7 +7075,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; optional = true; usesDefaultFeatures = false; } @@ -7307,9 +7378,9 @@ rec { }; "pest" = rec { crateName = "pest"; - version = "2.9.0"; + version = "2.9.2"; edition = "2021"; - sha256 = "1kwvhc5hyrfpxpmp0jw0wr891xyjs44mcs2wz68hrl54qw6ac1ss"; + sha256 = "1a11k95dyrpfrn2ql5lprdh4k31k4hksg83w67vfdlps62iarls5"; authors = [ "Dragoș Tiselice " ]; @@ -7336,9 +7407,9 @@ rec { }; "pest_derive" = rec { crateName = "pest_derive"; - version = "2.9.0"; + version = "2.9.2"; edition = "2021"; - sha256 = "13f8ihi8928s9mc13pcbhxy382kqc89h7i8d7s5mnif8lm23ga5k"; + sha256 = "1ky22vlsbqha1jhx5l31d95gm8l54va38b9zmmr2wjicgxan0jr8"; procMacro = true; authors = [ "Dragoș Tiselice " @@ -7364,9 +7435,9 @@ rec { }; "pest_generator" = rec { crateName = "pest_generator"; - version = "2.9.0"; + version = "2.9.2"; edition = "2021"; - sha256 = "0jihcdnmdban4bqjd02r2wbb79nywj2nhwqyk95hvrixm98k9kg0"; + sha256 = "029igkh6nsw62bn4325gkjm5c3lf4bjqbkv8jblrwc0ml441z78x"; authors = [ "Dragoș Tiselice " ]; @@ -7402,9 +7473,9 @@ rec { }; "pest_meta" = rec { crateName = "pest_meta"; - version = "2.9.0"; + version = "2.9.2"; edition = "2021"; - sha256 = "15jly0r7r4m15fhm3pg814h65j7dqnqq6k43rvgxfhg29443lkg0"; + sha256 = "1jxd8gbm328lsl3m0z2b1pq9ri60h4f7122i189k5jpwkwdbm4zd"; authors = [ "Dragoș Tiselice " ]; @@ -7559,9 +7630,9 @@ rec { }; "portable-atomic-util" = rec { crateName = "portable-atomic-util"; - version = "0.2.7"; + version = "0.2.8"; edition = "2018"; - sha256 = "0616j0fhy6y71hyxg3n86f6hng0fmsc269s3wp4gl8ww4p8hd8f2"; + sha256 = "059729m166s1ccvqfyj6lv0wz5kr4qh6yb2gphf3mk5yyfvkxaqh"; libName = "portable_atomic_util"; dependencies = [ { @@ -7605,9 +7676,9 @@ rec { }; "powerfmt" = rec { crateName = "powerfmt"; - version = "0.2.0"; + version = "0.2.1"; edition = "2021"; - sha256 = "14ckj2xdpkhv3h6l5sdmb9f1d57z8hbfpdldjc2vl5givq2y77j3"; + sha256 = "0n293rvnpisjmxdqhq6zmrvcdql7j1c4zrcy5053vrv5x6wr8qsa"; authors = [ "Jacob Pratt " ]; @@ -7840,11 +7911,11 @@ rec { "rustc-dep-of-std" = [ "core" ]; }; }; - "rand 0.10.2" = rec { + "rand 0.10.3" = rec { crateName = "rand"; - version = "0.10.2"; + version = "0.10.3"; edition = "2024"; - sha256 = "105yqkdzqbgggd3r1yjm9jg0zvibfdsmxylvxxkmblwc0lxgmxf7"; + sha256 = "1bxlhj4m9zrgfgk1yirf0nny86izrngscydfx9w387n9rfbgpjb5"; authors = [ "The Rand Project Developers" "The Rust Project Developers" @@ -8080,7 +8151,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.13.1"; + packageId = "bitflags 2.13.2"; } ]; features = { @@ -8128,7 +8199,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; @@ -8285,16 +8356,16 @@ rec { }; "reqwest" = rec { crateName = "reqwest"; - version = "0.13.4"; + version = "0.13.5"; edition = "2021"; - sha256 = "1hy1plns9krbh3h1dy2sdjygsfkdcnxm6pbxdi0ya9b5vq8mi711"; + sha256 = "0ac0n0g7xaffc6q3dhn9rixr4h1f0h7533l1smrxv1n1bjkwz88n"; authors = [ "Sean McArthur " ]; dependencies = [ { name = "base64"; - packageId = "base64 0.22.1"; + packageId = "base64 0.23.1"; } { name = "bytes"; @@ -8412,7 +8483,7 @@ rec { name = "web-sys"; packageId = "web-sys"; target = { target, features }: (("wasm32" == target."arch" or null) && (("unknown" == target."os" or null) || ("none" == target."os" or null))); - features = [ "AbortController" "AbortSignal" "Headers" "Request" "RequestInit" "RequestMode" "Response" "Window" "FormData" "Blob" "BlobPropertyBag" "ServiceWorkerGlobalScope" "RequestCredentials" "File" "ReadableStream" "RequestCache" ]; + features = [ "AbortController" "AbortSignal" "Headers" "Request" "RequestInit" "RequestMode" "Response" "Window" "FormData" "Blob" "BlobPropertyBag" "ServiceWorkerGlobalScope" "RequestCredentials" "File" "ReadableStream" "ReferrerPolicy" "RequestCache" ]; } ]; devDependencies = [ @@ -8916,9 +8987,9 @@ rec { }; "rustls-platform-verifier" = rec { crateName = "rustls-platform-verifier"; - version = "0.7.0"; + version = "0.7.1"; edition = "2021"; - sha256 = "181v4d0vl53vdh2wq56vghal1zyhdgqvy4xa8r45zwz4di9y5l96"; + sha256 = "164gb7kn9a8c0yrpqv879wf20z611qcfi4xjzf5qpcg2j5j5hrqi"; libName = "rustls_platform_verifier"; dependencies = [ { @@ -9022,7 +9093,7 @@ rec { name = "rustls"; packageId = "rustls"; usesDefaultFeatures = false; - features = [ "ring" ]; + features = [ "aws-lc-rs" ]; } { name = "webpki-root-certs"; @@ -9034,16 +9105,16 @@ rec { "base64" = [ "dep:base64" ]; "cert-logging" = [ "base64" ]; "docsrs" = [ "jni" "once_cell" ]; - "ffi-testing" = [ "android_logger" "rustls/ring" ]; + "ffi-testing" = [ "android_logger" "rustls/aws-lc-rs" ]; "jni" = [ "dep:jni" ]; "once_cell" = [ "dep:once_cell" ]; }; }; "rustls-platform-verifier-android" = rec { crateName = "rustls-platform-verifier-android"; - version = "0.1.1"; + version = "0.2.0"; edition = "2021"; - sha256 = "13vq6sxsgz9547xm2zbdxiw8x7ad1g8n8ax6xvxsjqszk7q6awgq"; + sha256 = "0pqsbv8656sr3h9jmq0q9848g03irccncywplmc29zs0pk08kipf"; libName = "rustls_platform_verifier_android"; }; @@ -9252,13 +9323,13 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; devDependencies = [ { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "extra-traits" ]; } ]; @@ -9369,7 +9440,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.13.1"; + packageId = "bitflags 2.13.2"; } { name = "core-foundation"; @@ -9640,7 +9711,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } @@ -9672,7 +9743,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" ]; } @@ -10041,7 +10112,7 @@ rec { features = { "default" = [ "std" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "aarch64_neon" "public_imp" "std" ]; }; "slab" = rec { crateName = "slab"; @@ -10303,7 +10374,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10340,7 +10411,7 @@ rec { } { name = "rand"; - packageId = "rand 0.10.2"; + packageId = "rand 0.10.3"; } { name = "rand_core"; @@ -10546,7 +10617,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10624,7 +10695,7 @@ rec { } { name = "rand"; - packageId = "rand 0.10.2"; + packageId = "rand 0.10.3"; } { name = "regex"; @@ -10745,7 +10816,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10768,7 +10839,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; @@ -10780,7 +10851,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10861,7 +10932,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -10971,7 +11042,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11021,7 +11092,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11073,7 +11144,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; @@ -11085,7 +11156,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "f3d2da737aa49086cbdaba806aaf2c8645251cfb"; + rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; @@ -11145,7 +11216,7 @@ rec { } { name = "rand"; - packageId = "rand 0.10.2"; + packageId = "rand 0.10.3"; } { name = "serde"; @@ -11363,13 +11434,13 @@ rec { "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "fold" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; - "syn 3.0.4" = rec { + "syn 3.0.6" = rec { crateName = "syn"; - version = "3.0.4"; + version = "3.0.6"; edition = "2021"; - sha256 = "17v4ac61x0hvj1879ywqzlwhyzg7n9lr9zniwrsif3b1ykfmq9z6"; + sha256 = "1vmw7s58rzrs926nv5m06x7qbgswm1aa9iw3s1bj5var47kyi4w5"; authors = [ "David Tolnay " ]; @@ -11396,7 +11467,7 @@ rec { "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "fold" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sync_wrapper" = rec { crateName = "sync_wrapper"; @@ -11422,9 +11493,9 @@ rec { }; "synstructure" = rec { crateName = "synstructure"; - version = "0.13.2"; + version = "0.14.0"; edition = "2018"; - sha256 = "1lh9lx3r3jb18f8sbj29am5hm9jymvbwh6jb1izsnnxgvgrp12kj"; + sha256 = "00kzyz38xqvs7x1dn6rp64y0ckly4m7ywf3qk3qkgqfzs3nh85wh"; authors = [ "Nika Layzell " ]; @@ -11441,7 +11512,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; + packageId = "syn 3.0.6"; usesDefaultFeatures = false; features = [ "derive" "parsing" "printing" "clone-impls" "visit" "extra-traits" ]; } @@ -11468,18 +11539,18 @@ rec { ]; }; - "thiserror 2.0.20" = rec { + "thiserror 2.0.21" = rec { crateName = "thiserror"; - version = "2.0.20"; + version = "2.0.21"; edition = "2021"; - sha256 = "0kxs6p295jffxhzaxpxv1dwaaf5iqlm6sx8h0djp6ancbxgj71pc"; + sha256 = "17hq1lh5dyr3bkc7zzjrbrp4qgkvhc48kgq1n5fdxkindaw2rr89"; authors = [ "David Tolnay " ]; dependencies = [ { name = "thiserror-impl"; - packageId = "thiserror-impl 2.0.20"; + packageId = "thiserror-impl 2.0.21"; } ]; features = { @@ -11513,11 +11584,11 @@ rec { ]; }; - "thiserror-impl 2.0.20" = rec { + "thiserror-impl 2.0.21" = rec { crateName = "thiserror-impl"; - version = "2.0.20"; + version = "2.0.21"; edition = "2021"; - sha256 = "1bwjc94gi0xn5jz26h1a8bjj1wdkvvr6jifamyc4mp9n28zcs15w"; + sha256 = "0945n8agp7kg6n6b35yyjb4g5xv2q22vrw15h6jj1nw76a99flgy"; procMacro = true; libName = "thiserror_impl"; authors = [ @@ -11534,7 +11605,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; } ]; @@ -11758,9 +11829,9 @@ rec { }; "tokio" = rec { crateName = "tokio"; - version = "1.53.1"; + version = "1.53.2"; edition = "2021"; - sha256 = "1v8b3b45pkpbibls75yniqbvx5dlks2708141ljni5mnf6lawb10"; + sha256 = "0i202ksji8q2asvii0adzgi8m0z93z3j7apn62qfh8d6qzy92pz9"; authors = [ "Tokio Contributors " ]; @@ -11898,7 +11969,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "full" ]; } ]; @@ -11906,9 +11977,9 @@ rec { }; "tokio-rustls" = rec { crateName = "tokio-rustls"; - version = "0.26.4"; + version = "0.26.6"; edition = "2021"; - sha256 = "0qggwknz9w4bbsv1z158hlnpkm97j3w8v31586jipn99byaala8p"; + sha256 = "1nq5s413p6hkwrgjrpag1gi2mnjajpbszqhmhbpnkmfdq9w2dk69"; libName = "tokio_rustls"; dependencies = [ { @@ -12079,9 +12150,9 @@ rec { }; "toml_edit" = rec { crateName = "toml_edit"; - version = "0.25.13+spec-1.1.0"; + version = "0.25.15+spec-1.1.0"; edition = "2024"; - sha256 = "16xgmjdnxssdpj7rjyimsk4fqbv29g8zl7zhdbc6dxrf9mz3cxb9"; + sha256 = "0556lgzcvgfy16b8sxskr391s6cbfwnb0r4h5i4k6qw5lnaflh0k"; dependencies = [ { name = "indexmap"; @@ -12449,7 +12520,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.13.1"; + packageId = "bitflags 2.13.2"; } { name = "bytes"; @@ -12574,7 +12645,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.13.1"; + packageId = "bitflags 2.13.2"; } { name = "bytes"; @@ -12749,7 +12820,7 @@ rec { } { name = "thiserror"; - packageId = "thiserror 2.0.20"; + packageId = "thiserror 2.0.21"; } { name = "time"; @@ -13125,9 +13196,9 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.24"; + version = "1.0.26"; edition = "2021"; - sha256 = "0xfs8y1g7syl2iykji8zk5hgfi5jw819f5zsrbaxmlzwsly33r76"; + sha256 = "0m3915ipi4zz7isncf5k1dz47ys0nq9j7l4l2n2rm03zaxwg8ifj"; libName = "unicode_ident"; authors = [ "David Tolnay " @@ -13284,9 +13355,9 @@ rec { }; "uuid" = rec { crateName = "uuid"; - version = "1.25.0"; + version = "1.27.0"; edition = "2021"; - sha256 = "1k5y394cmcrpl038i5szyxk96pa27nzgn89480d7cnph6ilmflzh"; + sha256 = "16h5h6bf5ybh1lj97lcdl41g7fqbiczpavpsb0zf3b63p4v7s9wp"; authors = [ "Ashley Mannix" "Dylan DPC" @@ -13398,9 +13469,9 @@ rec { }; "want" = rec { crateName = "want"; - version = "0.3.1"; + version = "0.3.2"; edition = "2018"; - sha256 = "03hbfrnvqqdchb5kgxyavb9jabwza0dmh2vw5kg0dq8rxl57d9xz"; + sha256 = "02zdlaqarwm9x3z1l0vm61mv8f6mv0kp4izgnxlfibqhv46xsk7c"; authors = [ "Sean McArthur " ]; @@ -13450,9 +13521,9 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.127"; + version = "0.2.129"; edition = "2021"; - sha256 = "0w6fa1mkbb6qlkffgy4qaz0hdf496zbjkyiyvs4lvmpd8xbr6w0v"; + sha256 = "02flhqld01jqb6vbfyx1gb8s78g1pnq2164daxad93y6mhrlzdcv"; libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" @@ -13483,12 +13554,6 @@ rec { rename = "rustversion-compat"; } ]; - devDependencies = [ - { - name = "once_cell"; - packageId = "once_cell"; - } - ]; features = { "default" = [ "std" ]; "enable-interning" = [ "std" ]; @@ -13501,9 +13566,9 @@ rec { }; "wasm-bindgen-futures" = rec { crateName = "wasm-bindgen-futures"; - version = "0.4.77"; + version = "0.4.79"; edition = "2021"; - sha256 = "0l3r8m335kb2p8yj65kb0biwlypcx3ay4g750hafkl13rkapfxvb"; + sha256 = "03k1wcg5j3wqk6vgy6gzcq868vsa9k81dlhqissfk0nrw96v7fiw"; libName = "wasm_bindgen_futures"; authors = [ "The wasm-bindgen Developers" @@ -13514,6 +13579,13 @@ rec { packageId = "js-sys"; usesDefaultFeatures = false; } + { + name = "tokio"; + packageId = "tokio"; + usesDefaultFeatures = false; + target = { target, features }: (("emscripten" == target."os" or null) && (target."wasm_bindgen_unstable_tokio" or false)); + features = [ "rt" "time" ]; + } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; @@ -13529,9 +13601,9 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.127"; + version = "0.2.129"; edition = "2021"; - sha256 = "1hcvlb6bv771fvgifd367wd0cm4giyar8fq5i4h705vj7y7myxvp"; + sha256 = "0dc5xq09sy1v9ns1fhb0cnyqz5p1wcjjvkdmxskj9qhnbg1x0a9f"; procMacro = true; libName = "wasm_bindgen_macro"; authors = [ @@ -13553,9 +13625,9 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.127"; + version = "0.2.129"; edition = "2021"; - sha256 = "112j4d7dv8y2sk9yy9czrl9fpjx9388ywnn7icdv2bywazw367g1"; + sha256 = "1dx6w90f14avmhri7ss9lyz03060g6475r4axy3bm7biqf5ill3g"; libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" @@ -13575,7 +13647,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; + packageId = "syn 3.0.6"; features = [ "visit" "visit-mut" "full" "extra-traits" ]; } { @@ -13589,10 +13661,10 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.127"; + version = "0.2.129"; edition = "2021"; links = "wasm_bindgen"; - sha256 = "1gywp6xv8a27fvm3ga9xby93xyic3hc2s626b9z9rw2xqny4vxky"; + sha256 = "1ilmp5d3sl8lrq9djhcs90gk66yvk8mgwk4sfrvpvkd75b2wkw13"; libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" @@ -13607,9 +13679,9 @@ rec { }; "web-sys" = rec { crateName = "web-sys"; - version = "0.3.104"; + version = "0.3.106"; edition = "2021"; - sha256 = "0c0acbvaqzqf21q5vdff2g74fvb7afi91xjplmclybq4d24k6df4"; + sha256 = "195bd1m14w3hsw5fg3sr938mh7y4cb260d0sq6a6brffxjfin9l8"; libName = "web_sys"; authors = [ "The wasm-bindgen Developers" @@ -14104,7 +14176,7 @@ rec { "default" = [ "std" ]; "std" = [ "wasm-bindgen/std" "js-sys/std" ]; }; - resolvedDefaultFeatures = [ "AbortController" "AbortSignal" "Blob" "BlobPropertyBag" "EventTarget" "File" "FormData" "Headers" "ReadableStream" "Request" "RequestCache" "RequestCredentials" "RequestInit" "RequestMode" "Response" "ServiceWorkerGlobalScope" "Window" "WorkerGlobalScope" "default" "std" ]; + resolvedDefaultFeatures = [ "AbortController" "AbortSignal" "Blob" "BlobPropertyBag" "EventTarget" "File" "FormData" "Headers" "ReadableStream" "ReferrerPolicy" "Request" "RequestCache" "RequestCredentials" "RequestInit" "RequestMode" "Response" "ServiceWorkerGlobalScope" "Window" "WorkerGlobalScope" "default" "std" ]; }; "web-time" = rec { crateName = "web-time"; @@ -15106,9 +15178,9 @@ rec { }; "yoke-derive" = rec { crateName = "yoke-derive"; - version = "0.8.2"; + version = "0.8.4"; edition = "2021"; - sha256 = "13l5y5sz4lqm7rmyakjbh6vwgikxiql51xfff9hq2j485hk4r16y"; + sha256 = "0wbdvvdv9birwxrr9ynxj0k7as0f0ci7ihhck34yi09nvgibv3pc"; procMacro = true; libName = "yoke_derive"; authors = [ @@ -15125,8 +15197,8 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; - features = [ "fold" ]; + packageId = "syn 3.0.6"; + features = [ "fold" "visit" ]; } { name = "synstructure"; @@ -15137,9 +15209,9 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.8.56"; + version = "0.8.60"; edition = "2021"; - sha256 = "1svmifchgdk0sm7v24lfwhhxis57gwa2lg21ingmmd5dhgjn8rsm"; + sha256 = "1ghxkd4fv4ka88v2rg9260p6465v49hmc1zvqfm6yvs2nx5zq034"; dependencies = [ { name = "zerocopy-derive"; @@ -15169,9 +15241,9 @@ rec { }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.8.56"; + version = "0.8.60"; edition = "2021"; - sha256 = "1hfz1hfxj86y1sgyia8gbisny9bl9bwlbahg4jypjmsp43y45azj"; + sha256 = "1nrlkb37wm1sq962725mxwhahaicbg277q25kbslvbavab3prhlr"; procMacro = true; libName = "zerocopy_derive"; dependencies = [ @@ -15222,9 +15294,9 @@ rec { }; "zerofrom-derive" = rec { crateName = "zerofrom-derive"; - version = "0.1.7"; + version = "0.1.8"; edition = "2021"; - sha256 = "18c4wsnznhdxx6m80piil1lbyszdiwsshgjrybqcm4b6qic22lqi"; + sha256 = "0jhdy4p9c6ja3dynsdck14g2iilq8ai5ch6nsi455x67ys1lcnzp"; procMacro = true; libName = "zerofrom_derive"; authors = [ @@ -15241,8 +15313,8 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; - features = [ "fold" ]; + packageId = "syn 3.0.6"; + features = [ "fold" "visit" ]; } { name = "synstructure"; @@ -15408,12 +15480,29 @@ rec { } { name = "syn"; - packageId = "syn 3.0.4"; + packageId = "syn 3.0.6"; features = [ "extra-traits" ]; } ]; }; + "zlib-rs" = rec { + crateName = "zlib-rs"; + version = "0.6.8"; + edition = "2021"; + sha256 = "04j158293bx73kv5pj1i89ai411q7fxc9zwk3wkpqgb9gj7fas5j"; + libName = "zlib_rs"; + features = { + "__internal-fuzz" = [ "arbitrary" ]; + "__internal-test" = [ "quickcheck" ]; + "arbitrary" = [ "dep:arbitrary" ]; + "avx512" = [ "vpclmulqdq" ]; + "default" = [ "std" "c-allocator" ]; + "quickcheck" = [ "dep:quickcheck" ]; + "std" = [ "rust-allocator" ]; + }; + resolvedDefaultFeatures = [ "rust-allocator" "std" ]; + }; "zmij" = rec { crateName = "zmij"; version = "1.0.23"; diff --git a/extra/crds.yaml b/extra/crds.yaml index eb762d076..fe7d18a42 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -2141,11 +2141,16 @@ spec: nullable: true properties: authentication: - description: The credential the agent authenticates to Kafka with. + description: How the agent authenticates to Kafka. oneOf: - required: - tls + - required: + - anonymous properties: + anonymous: + description: 'No credential: the product does not authenticate the agent.' + type: object tls: description: 'Source of a TLS client certificate: a secret-operator SecretClass or a static Secret.' oneOf: diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 35db34806..e9dc87ca9 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -47,6 +47,7 @@ pub fn build_agent_deployment( KafkaPlatformAccessAuthentication::Tls(credential) => { credential.add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) } + KafkaPlatformAccessAuthentication::Anonymous(_) => {} } cb_agent @@ -259,6 +260,15 @@ mod tests { ); } + #[test] + fn deployment_with_anonymous_authentication_mounts_no_credential() { + let deployment = agent_deployment("{enabled: true, authentication: {anonymous: {}}}"); + + let pod_spec = &deployment["spec"]["template"]["spec"]; + assert_eq!(pod_spec["volumes"], Value::Null); + assert_eq!(pod_spec["containers"][0]["volumeMounts"], Value::Null); + } + #[test] fn test_deployment_uses_product_image_pull_secrets() { let cluster = cluster_with_image( diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 7f486d93b..b09942d88 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -12,8 +12,10 @@ use serde::{Deserialize, Serialize}; use snafu::Snafu; use stackable_operator::{ commons::{ - cluster_operation::ClusterOperation, networking::DomainName, - platform_access::tls::TlsClientCredential, product_image_selection::ProductImage, + cluster_operation::ClusterOperation, + networking::DomainName, + platform_access::{anonymous::Anonymous, tls::TlsClientCredential}, + product_image_selection::ProductImage, }, config::merge::Merge, constant, @@ -116,7 +118,7 @@ pub struct KafkaPlatformAccess { #[serde(default)] pub enabled: bool, - /// The credential the agent authenticates to Kafka with. + /// How the agent authenticates to Kafka. pub authentication: KafkaPlatformAccessAuthentication, } @@ -125,6 +127,7 @@ pub struct KafkaPlatformAccess { #[serde(rename_all = "camelCase")] pub enum KafkaPlatformAccessAuthentication { Tls(TlsClientCredential), + Anonymous(Anonymous), } #[versioned( From 18a4ff2f610a9f6e2ff8e8881a04f50203417d24 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 13 Oct 2026 11:23:09 +0200 Subject: [PATCH 09/25] use versioned for platform access CRD fragments --- Cargo.lock | 222 ++++++++------ Cargo.nix | 283 +++++++++++------- extra/crds.yaml | 4 +- rust/operator-binary/src/controller.rs | 5 +- .../src/controller/build/resource/agent.rs | 2 +- rust/operator-binary/src/crd/mod.rs | 49 ++- 6 files changed, 326 insertions(+), 239 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da8c1babd..bbeb84616 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,7 +169,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -316,9 +316,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ "find-msvc-tools", "jobserver", @@ -385,7 +385,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -575,7 +575,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -597,7 +597,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core 0.24.1", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e" [[package]] name = "derive_more" @@ -713,7 +713,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -777,14 +777,14 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "either" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "elliptic-curve" @@ -855,7 +855,7 @@ checksum = "a65863d15a4ce2888bd2f0f543cc963d3879c3a022c8ee43f6141d479a3ac815" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -1010,7 +1010,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -1149,9 +1149,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" dependencies = [ "atomic-waker", "bytes", @@ -1262,9 +1262,9 @@ checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hyper" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c" dependencies = [ "atomic-waker", "bytes", @@ -1482,9 +1482,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1" dependencies = [ "rustversion", ] @@ -1538,9 +1538,9 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +checksum = "b2b005715dcbeb0089a3c0dab99f2ff1cc3b2525323552703d648585d342a383" dependencies = [ "defmt", "jiff-core", @@ -1565,9 +1565,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +checksum = "2cc9817253cf7c7ee4684451bd327e88d6f3658014e54a29198625590650695c" dependencies = [ "jiff-core", "proc-macro2", @@ -1577,9 +1577,9 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" +checksum = "fa8377070c6bae868759445e5a77f66d84f0b72f3a054bfb00e6d038b8282da7" [[package]] name = "jiff-tzdb-platform" @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "darling 0.24.1", "regex", @@ -1878,9 +1878,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libz-sys" -version = "1.1.29" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" +checksum = "f710a23e6dbf193214fd46ca56a9d6864e550abe86202184532ae7275e46de19" dependencies = [ "cc", "libc", @@ -2049,9 +2049,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opentelemetry" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cdb0b1b267eb9db3331b434ed9ddab10d50e280a9adf9d13e5233e2002b61b5" +checksum = "8c1f1a6ac9c875a4941e4c7c085b61e8f4daa326de03b4701768c3491a6ad9ee" dependencies = [ "futures-core", "futures-sink", @@ -2063,9 +2063,9 @@ dependencies = [ [[package]] name = "opentelemetry-appender-tracing" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b304e8d8f11326ba366a99ca5c7aaf7cd397b67268a332437175aeb42a40db" +checksum = "1f01f1c53c46ce80e5fd8cb7a646f13766fd8f315a8a5b75b9bad59a08d2c5c7" dependencies = [ "opentelemetry", "tracing", @@ -2075,9 +2075,9 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2c3625b8aa04209f7e01e513bc8044da9687fa38a9eacf59628ca5f3b87300" +checksum = "302249bd8ee804789faaa7b5b2cbf79bc61cb864714079c644e3828af5b7e811" dependencies = [ "async-trait", "bytes", @@ -2088,9 +2088,9 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "699a67345e21962a231955b9059a157e428b219fa5df8efe11f08346fb23a344" +checksum = "0756af24841e367128ef31c831999937b8b5c5197d47914590d8f4e2e88c2e1a" dependencies = [ "http", "httpdate", @@ -2108,9 +2108,9 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25da1ac11a0aeccf38d7f77ee0348715adaf8340f65ad46c94a02c6b20e2f65d" +checksum = "d576f5dddc3299341bcd85a04be17b2564844c0c9563214f02d85f2524d1afae" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -2121,15 +2121,15 @@ dependencies = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d288b1e1bc3590052fbb8f0f635ef248dd9022cf1fbaeb6582b7ad6081a17b87" +checksum = "7a3cf639fefd3e852869114f9925b578da6dd8e99281a2089bb0e773ead46962" [[package]] name = "opentelemetry_sdk" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb39533d9d1c912123efd7d41d7e0c29d16917b60ce15b4c8d87cb1af7f67520" +checksum = "372a912db2974d1990207006fd0e3aa0ef3fd4ad3be43c65cfaadf2206866061" dependencies = [ "futures-channel", "futures-executor", @@ -2220,19 +2220,21 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8" +checksum = "b568374ba38b33a6c627141f891faf16902b08d2db26b8ede1bcb0a15b1919fa" dependencies = [ "memchr", + "psm", + "stacker", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf" +checksum = "b66e184b924cebaaff20ab2256ca52f12332d528a39aa76553b5d96f92aacf7f" dependencies = [ "pest", "pest_generator", @@ -2240,22 +2242,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109" +checksum = "a87478d267e4de54a626af9754f2f0f58e927aac6ed0575fe89bc05ad6851694" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.9", ] [[package]] name = "pest_meta" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb" +checksum = "4f986f248b4241ac359b831f6139aaa34e03b08a37b6caf7e201a33f95c869e1" dependencies = [ "pest", ] @@ -2411,6 +2413,15 @@ dependencies = [ "prost", ] +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + [[package]] name = "quote" version = "1.0.47" @@ -2533,7 +2544,7 @@ checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2791,9 +2802,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +checksum = "ab508826f74a77ca9d5aba6ff19b522583ee3eaf28a19384ff3d0e5835fadf6e" dependencies = [ "dyn-clone", "ref-cast", @@ -2805,14 +2816,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" +checksum = "e1c3a92094fa7d61aa124645844facb6b554dfc797136d0f5fd1f890e2bffc69" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2933,7 +2944,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2944,14 +2955,14 @@ checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -3164,7 +3175,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "const-oid", "ecdsa", @@ -3222,7 +3233,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.119.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "base64 0.23.1", "clap", @@ -3266,18 +3277,18 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "darling 0.24.1", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "stackable-shared" version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "jiff", "k8s-openapi", @@ -3294,7 +3305,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "axum", "clap", @@ -3318,7 +3329,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "kube", "schemars", @@ -3332,7 +3343,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "convert_case", "darling 0.24.1", @@ -3343,13 +3354,13 @@ dependencies = [ "kube", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#3b91d73a3e66639654597d6304780b5ccc75d9c0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#754e444b8cc3daf6a59fb69d7eaf632249ccc3be" dependencies = [ "arc-swap", "async-trait", @@ -3378,6 +3389,19 @@ dependencies = [ "x509-cert", ] +[[package]] +name = "stacker" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.61.2", +] + [[package]] name = "strsim" version = "0.11.1" @@ -3441,9 +3465,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", @@ -3467,7 +3491,7 @@ checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -3507,7 +3531,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -3605,7 +3629,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -3631,9 +3655,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", @@ -3646,18 +3670,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.25.15+spec-1.1.0" +version = "0.25.17+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" dependencies = [ "indexmap", "toml_datetime", @@ -3667,9 +3691,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" dependencies = [ "winnow", ] @@ -3916,9 +3940,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-ident" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-segmentation" @@ -3977,9 +4001,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ "js-sys", "wasm-bindgen", @@ -4080,7 +4104,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "wasm-bindgen-shared", ] @@ -4332,24 +4356,24 @@ checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.60" +version = "0.8.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6400fc4bb7426f6faac3fb07566122bb18622e3022bd2c36426a92ed489b1dbe" +checksum = "86502bf56ac7c77571a32e2647bb2a15894565e981fb2a48d7bde2d91c965a9d" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.60" +version = "0.8.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c27cc7525bad4df59a45e073c45b2c2aa820efb588234cc23a547ec69a34db" +checksum = "5457206954b06561e2608c7e19cf58b1926586d999c246eebe4502f7e2039d1a" dependencies = [ "proc-macro2", "quote", @@ -4373,15 +4397,15 @@ checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] [[package]] name = "zeroize" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" dependencies = [ "zeroize_derive", ] @@ -4427,7 +4451,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] diff --git a/Cargo.nix b/Cargo.nix index 17baabbeb..116feeff6 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -506,7 +506,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; usesDefaultFeatures = false; features = [ "clone-impls" "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } @@ -987,9 +987,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.6.0"; + version = "1.8.0"; edition = "2021"; - sha256 = "0c3n82hdi355xa6z9x4zgnpjwsh1szkkcs0zl8q8nl5ggk874j7p"; + sha256 = "0f6q6vc8fj6xn4j1wd4yakiza6lhgwai49gp1zdwgzggh3nwjlb6"; dependencies = [ { name = "find-msvc-tools"; @@ -1218,7 +1218,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "full" ]; } ]; @@ -1765,7 +1765,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "full" "extra-traits" ]; } ]; @@ -1821,7 +1821,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; @@ -2006,9 +2006,9 @@ rec { }; "deranged" = rec { crateName = "deranged"; - version = "0.5.8"; - edition = "2021"; - sha256 = "0711df3w16vx80k55ivkwzwswziinj4dz05xci3rvmn15g615n3w"; + version = "0.5.9"; + edition = "2024"; + sha256 = "13nj445c8frp617vx84g1m5yp1gg63sg09gscbf907xdw8nfg7cy"; authors = [ "Jacob Pratt " ]; @@ -2189,7 +2189,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; features = { @@ -2397,7 +2397,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "visit" "visit-mut" ]; } ]; @@ -2409,9 +2409,9 @@ rec { }; "either" = rec { crateName = "either"; - version = "1.18.0"; + version = "1.19.0"; edition = "2021"; - sha256 = "0d7dx31sf8rakcgp63070ngb2vkjynrni866pnx879pawndgnai5"; + sha256 = "1gjq21g0sgk5ylpj85zafcinwhh3jj91i6drhb4278vw2v17370f"; features = { "default" = [ "std" ]; "serde" = [ "dep:serde" ]; @@ -2645,7 +2645,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; features = { @@ -3091,7 +3091,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "full" ]; } ]; @@ -3616,9 +3616,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.4.19"; + version = "0.4.20"; edition = "2021"; - sha256 = "05mw60jmsq97vjgj607nxjkx8dl6rxv6jj9i4r2z92056id5x3pg"; + sha256 = "0661bxispf05ik0idbjlyabwyqpngh9c2r6avaqkzann68104abx"; authors = [ "Carl Lerche " "Sean McArthur " @@ -3927,9 +3927,9 @@ rec { }; "hyper" = rec { crateName = "hyper"; - version = "1.11.1"; + version = "1.12.0"; edition = "2021"; - sha256 = "0hxyikj5livhmw5q3x3ifyhphh1g2cjsc32nsg1jcyhflpx03d97"; + sha256 = "173wg6msakx4lha6hxm9z0i1h3bw34q8fk0x57b7flf9li6k4gic"; authors = [ "Sean McArthur " ]; @@ -4023,7 +4023,7 @@ rec { "client" = [ "dep:want" "dep:pin-project-lite" "dep:smallvec" ]; "ffi" = [ "dep:http-body-util" "dep:futures-util" ]; "full" = [ "client" "http1" "http2" "server" ]; - "http1" = [ "dep:atomic-waker" "dep:futures-channel" "dep:futures-core" "dep:httparse" "dep:itoa" ]; + "http1" = [ "dep:atomic-waker" "dep:futures-core" "dep:httparse" "dep:itoa" ]; "http2" = [ "dep:atomic-waker" "dep:futures-channel" "dep:futures-core" "dep:h2" ]; "server" = [ "dep:httpdate" "dep:pin-project-lite" "dep:smallvec" ]; "tracing" = [ "dep:tracing" ]; @@ -4765,9 +4765,9 @@ rec { }; "indoc" = rec { crateName = "indoc"; - version = "2.0.7"; + version = "2.0.8"; edition = "2021"; - sha256 = "01np60qdq6lvgh8ww2caajn9j4dibx9n58rvzf7cya1jz69mrkvr"; + sha256 = "1lc4agds9bqf3lin6kkz2jgmahaqwrkaq1fkij5fpzvcg68jcyx3"; procMacro = true; authors = [ "David Tolnay " @@ -4896,9 +4896,9 @@ rec { }; "jiff" = rec { crateName = "jiff"; - version = "0.2.37"; + version = "0.2.38"; edition = "2021"; - sha256 = "1nxgdj2wajw9ml8fcc2zq858k6v9618m22864vh6sy885zvvmc8a"; + sha256 = "10x38b9qb1b47mq54d9j4ljkpk7i5ygvknn0lf4h1sybbmqhbc5j"; authors = [ "Andrew Gallant " ]; @@ -5021,9 +5021,9 @@ rec { }; "jiff-static" = rec { crateName = "jiff-static"; - version = "0.2.37"; + version = "0.2.38"; edition = "2021"; - sha256 = "04kjdzg4h4wy38ghm91qva7xg4glr65120c74bk7mmka26hni0ip"; + sha256 = "0p39a035j9c634llmr8lh1jz7ml8gqrbsla4d3j7wz6gadr83j9c"; procMacro = true; libName = "jiff_static"; authors = [ @@ -5055,9 +5055,9 @@ rec { }; "jiff-tzdb" = rec { crateName = "jiff-tzdb"; - version = "0.1.8"; + version = "0.1.9"; edition = "2021"; - sha256 = "07hl9sgzfb9as1x0n5bjk1qxishzcriapy9xa481y8xd6acx6aql"; + sha256 = "19rd52w3il7603xln19s5yvz113dyrvmlpj4b63qdbkb1h3pg0zs"; libName = "jiff_tzdb"; libPath = "lib.rs"; authors = [ @@ -5444,7 +5444,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -6178,10 +6178,10 @@ rec { }; "libz-sys" = rec { crateName = "libz-sys"; - version = "1.1.29"; + version = "1.1.30"; edition = "2018"; links = "z"; - sha256 = "1n98kqya7a7a0cxf5n5z3g13rj7a1vqxynk2xc7bja1qfxbrdg45"; + sha256 = "06fy8rg2grraaf222846pq55akl6sslmdjj6zla346dzdlza447p"; libName = "libz_sys"; authors = [ "Alex Crichton " @@ -6671,9 +6671,9 @@ rec { }; "opentelemetry" = rec { crateName = "opentelemetry"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "1db15c0f4csj7v8zkbd9h3i503divafysd5l64rxpfby4qdhpnvc"; + sha256 = "1vnrd8d4khv82xqb80yy4sixmx78c5dhhz2c3saa8xf8r5m1l7wc"; dependencies = [ { name = "futures-core"; @@ -6725,9 +6725,9 @@ rec { }; "opentelemetry-appender-tracing" = rec { crateName = "opentelemetry-appender-tracing"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "1ns05asawxbi8cra6s3jnsbx6z5gg9fcm6ba6sx2c4ziv3l09cz2"; + sha256 = "1iy5s849mmdsp5smp2js667zsripy53addwczpjq1kj67k2z208z"; libName = "opentelemetry_appender_tracing"; dependencies = [ { @@ -6776,9 +6776,9 @@ rec { }; "opentelemetry-http" = rec { crateName = "opentelemetry-http"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "003kp3rsb332b77yma9qza3rdnj4h2y17r81gsgj015ap0jkcb7f"; + sha256 = "04g8nzsqm0p38k37jh3icjw1rilvyz5v5dd7magph178isylj8ih"; libName = "opentelemetry_http"; dependencies = [ { @@ -6820,9 +6820,9 @@ rec { }; "opentelemetry-otlp" = rec { crateName = "opentelemetry-otlp"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "0i534gxld0zh27z8xpx5kwhqnhky2nd0bfam34ijm5i1bqs6g6k9"; + sha256 = "06ifiklf5x6qj12r2ivx372vbf1pk6ck3j1ixwl72dhyhhjaymh7"; libName = "opentelemetry_otlp"; dependencies = [ { @@ -6952,9 +6952,9 @@ rec { }; "opentelemetry-proto" = rec { crateName = "opentelemetry-proto"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "0pgnw8h6nb50jind8npn821szb8mhwsf0zppswwczv0a3b0imni5"; + sha256 = "1bmgs4j2apyq097j2qwm1i688r15gghlp845rldk969jvkfzaxnm"; libName = "opentelemetry_proto"; dependencies = [ { @@ -7018,9 +7018,9 @@ rec { }; "opentelemetry-semantic-conventions" = rec { crateName = "opentelemetry-semantic-conventions"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "11vvl60n1bdph9jypfhzrwi91pa8y9g663wgpcphb41mpkhv326j"; + sha256 = "0qk9skm77rxhkc4a50cjx7c6vnkqnljrjkqid4l8agpxzqwzcg3s"; libName = "opentelemetry_semantic_conventions"; features = { }; @@ -7028,9 +7028,9 @@ rec { }; "opentelemetry_sdk" = rec { crateName = "opentelemetry_sdk"; - version = "0.33.0"; + version = "0.33.1"; edition = "2021"; - sha256 = "083myvvimjw7im65pq8cnqbnkl991iz1vm6pxwij348wklym6ffb"; + sha256 = "0qb0hq325pxarxjkrr1vmpa3zvx0787gs1kh4281jkcpn8nr2aip"; dependencies = [ { name = "futures-channel"; @@ -7378,9 +7378,9 @@ rec { }; "pest" = rec { crateName = "pest"; - version = "2.9.2"; + version = "2.9.3"; edition = "2021"; - sha256 = "1a11k95dyrpfrn2ql5lprdh4k31k4hksg83w67vfdlps62iarls5"; + sha256 = "1yhr35ds3c5ww7nvh9nvs842p40nmwgqj7ql4z3accwbld5kfs5m"; authors = [ "Dragoș Tiselice " ]; @@ -7390,6 +7390,16 @@ rec { packageId = "memchr"; optional = true; } + { + name = "psm"; + packageId = "psm"; + optional = true; + } + { + name = "stacker"; + packageId = "stacker"; + optional = true; + } { name = "ucd-trie"; packageId = "ucd-trie"; @@ -7401,15 +7411,15 @@ rec { "memchr" = [ "dep:memchr" ]; "miette-error" = [ "std" "pretty-print" "dep:miette" ]; "pretty-print" = [ "dep:serde" "dep:serde_json" ]; - "std" = [ "ucd-trie/std" ]; + "std" = [ "ucd-trie/std" "dep:stacker" "dep:psm" ]; }; resolvedDefaultFeatures = [ "default" "memchr" "std" ]; }; "pest_derive" = rec { crateName = "pest_derive"; - version = "2.9.2"; + version = "2.9.3"; edition = "2021"; - sha256 = "1ky22vlsbqha1jhx5l31d95gm8l54va38b9zmmr2wjicgxan0jr8"; + sha256 = "0zygma96zndmadjsg6m353ak48ziab55c8mb43zsmsscj95ihvmn"; procMacro = true; authors = [ "Dragoș Tiselice " @@ -7435,9 +7445,9 @@ rec { }; "pest_generator" = rec { crateName = "pest_generator"; - version = "2.9.2"; + version = "2.9.3"; edition = "2021"; - sha256 = "029igkh6nsw62bn4325gkjm5c3lf4bjqbkv8jblrwc0ml441z78x"; + sha256 = "150nhpb5mh4vx1gmgl3fmix953pmy3r595xg4sk59pp4cz97hx58"; authors = [ "Dragoș Tiselice " ]; @@ -7461,7 +7471,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.119"; + packageId = "syn 3.0.9"; } ]; features = { @@ -7473,9 +7483,9 @@ rec { }; "pest_meta" = rec { crateName = "pest_meta"; - version = "2.9.2"; + version = "2.9.3"; edition = "2021"; - sha256 = "1jxd8gbm328lsl3m0z2b1pq9ri60h4f7122i189k5jpwkwdbm4zd"; + sha256 = "1qb9r2akz8q1wbvwmdipiaq06km3m8wn27w3kcssqha2icj6z62g"; authors = [ "Dragoș Tiselice " ]; @@ -7867,6 +7877,22 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "psm" = rec { + crateName = "psm"; + version = "0.1.24"; + edition = "2015"; + sha256 = "0428cnwx8i9dhkcjwzap0amg9cjk8nhj0xr5hkhm6zl543r9y2r0"; + authors = [ + "Simonas Kazlauskas " + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + + }; "quote" = rec { crateName = "quote"; version = "1.0.47"; @@ -8199,7 +8225,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; @@ -9222,9 +9248,9 @@ rec { }; "schemars" = rec { crateName = "schemars"; - version = "1.2.2"; + version = "1.2.3"; edition = "2021"; - sha256 = "0jng632s64njf9vghr3i1l4m15h4y85m5vhg7vkwdkdnjg978wk8"; + sha256 = "0vnzz8smh3ixzy297898mwzfx0r5aadz2vxsbafwlxsaywk8hl5b"; authors = [ "Graham Esau " ]; @@ -9301,9 +9327,9 @@ rec { }; "schemars_derive" = rec { crateName = "schemars_derive"; - version = "1.2.2"; + version = "1.2.3"; edition = "2021"; - sha256 = "1fp2wkdk32nv66swy7k7pz7sxygn634snlppih5jzbs6ddqng36r"; + sha256 = "0sgwpzi91y6ibw7ns4wpqzgm9ddnmi7q8ia62am62zgsjhhakhz1"; procMacro = true; authors = [ "Graham Esau " @@ -9323,13 +9349,13 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; devDependencies = [ { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "extra-traits" ]; } ]; @@ -9711,7 +9737,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } @@ -9743,7 +9769,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" ]; } @@ -9752,13 +9778,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.151"; + version = "1.0.154"; edition = "2021"; - sha256 = "051zww7lvpw147vvwss1ng6w587qyrkzg75fvj08q2dfrmgbahf8"; - authors = [ - "Erick Tryzelaar " - "David Tolnay " - ]; + sha256 = "1mjby21g8fxhrsfp73yz8wg6n2f4h23ah0nczds409l53f5wrsg7"; dependencies = [ { name = "itoa"; @@ -9796,7 +9818,7 @@ rec { "alloc" = [ "serde_core/alloc" ]; "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; - "preserve_order" = [ "indexmap" "std" ]; + "preserve_order" = [ "indexmap" "alloc" "dep:foldhash" ]; "std" = [ "memchr/std" "serde_core/std" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "raw_value" "std" ]; @@ -10374,7 +10396,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10617,7 +10639,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10816,7 +10838,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10839,7 +10861,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; @@ -10851,7 +10873,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10932,7 +10954,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -11042,7 +11064,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11092,7 +11114,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11144,7 +11166,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; @@ -11156,7 +11178,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "3b91d73a3e66639654597d6304780b5ccc75d9c0"; + rev = "754e444b8cc3daf6a59fb69d7eaf632249ccc3be"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; @@ -11280,6 +11302,49 @@ rec { } ]; + }; + "stacker" = rec { + crateName = "stacker"; + version = "0.1.25"; + edition = "2021"; + sha256 = "0rwrws4iyh8cay7pghzf2dy55pprwfn1vm805f5czfh6cza4jzvh"; + authors = [ + "Alex Crichton " + "Simonas Kazlauskas " + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "psm"; + packageId = "psm"; + } + { + name = "windows-sys"; + packageId = "windows-sys 0.61.2"; + target = { target, features }: (target.name == "arm64ec-pc-windows-msvc"); + features = [ "Win32_System_Memory" "Win32_System_Threading" "Win32_Foundation" ]; + } + { + name = "windows-sys"; + packageId = "windows-sys 0.61.2"; + target = { target, features }: ((target."windows" or false) && (!("arm64ec" == target."arch" or null))); + features = [ "Win32_System_Memory" "Win32_System_Threading" "Win32_Foundation" ]; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + }; "strsim" = rec { crateName = "strsim"; @@ -11436,11 +11501,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; - "syn 3.0.6" = rec { + "syn 3.0.9" = rec { crateName = "syn"; - version = "3.0.6"; + version = "3.0.9"; edition = "2021"; - sha256 = "1vmw7s58rzrs926nv5m06x7qbgswm1aa9iw3s1bj5var47kyi4w5"; + sha256 = "0fw28lhl90kls24q2h2sp39yjb0lsvz5cwh9fd3f3w3v9kp8v36p"; authors = [ "David Tolnay " ]; @@ -11512,7 +11577,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; usesDefaultFeatures = false; features = [ "derive" "parsing" "printing" "clone-impls" "visit" "extra-traits" ]; } @@ -11605,7 +11670,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; } ]; @@ -11969,7 +12034,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "full" ]; } ]; @@ -12060,9 +12125,9 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.19"; + version = "0.7.20"; edition = "2021"; - sha256 = "0licqrhrawysjrsr0qw3cgzkkjph7090hlcqcm45aazmkg81aj29"; + sha256 = "0jwagxx9vr940rlxjh0y7zimd2cbxqbjym5nz73byvm93d2wyr74"; libName = "tokio_util"; authors = [ "Tokio Contributors " @@ -12129,9 +12194,9 @@ rec { }; "toml_datetime" = rec { crateName = "toml_datetime"; - version = "1.1.1+spec-1.1.0"; + version = "1.1.2+spec-1.1.0"; edition = "2024"; - sha256 = "1mws2mkkf46l7inn77azhm0vdwxngv9vsbhbl0ah33p2c9gzcr9i"; + sha256 = "0lrhcmqvhjr259w4f2kijya7fgi0kpmhg9fb3m144v3cj1kxg1ib"; dependencies = [ { name = "serde_core"; @@ -12150,9 +12215,9 @@ rec { }; "toml_edit" = rec { crateName = "toml_edit"; - version = "0.25.15+spec-1.1.0"; + version = "0.25.17+spec-1.1.0"; edition = "2024"; - sha256 = "0556lgzcvgfy16b8sxskr391s6cbfwnb0r4h5i4k6qw5lnaflh0k"; + sha256 = "174w1b2fjg1jb0wi7384v1m59g7ga79458i022gafjakpddisr73"; dependencies = [ { name = "indexmap"; @@ -12185,9 +12250,9 @@ rec { }; "toml_parser" = rec { crateName = "toml_parser"; - version = "1.1.3+spec-1.1.0"; + version = "1.1.5+spec-1.1.0"; edition = "2024"; - sha256 = "0mjdvihdkmjd4ykh574xgii71hpxw7ns7h4n4bisqpxrz4faqf0x"; + sha256 = "0k3lljyi4zxchdklaqghkwbl7wkd2ab1w16hlyniqzid0fl979ms"; dependencies = [ { name = "winnow"; @@ -13196,9 +13261,9 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.26"; + version = "1.0.27"; edition = "2021"; - sha256 = "0m3915ipi4zz7isncf5k1dz47ys0nq9j7l4l2n2rm03zaxwg8ifj"; + sha256 = "0qv54hz0sxmspjyr162z3435pnyylzjjhx3j4k1s359pqgb59ix2"; libName = "unicode_ident"; authors = [ "David Tolnay " @@ -13355,9 +13420,9 @@ rec { }; "uuid" = rec { crateName = "uuid"; - version = "1.27.0"; + version = "1.28.0"; edition = "2021"; - sha256 = "16h5h6bf5ybh1lj97lcdl41g7fqbiczpavpsb0zf3b63p4v7s9wp"; + sha256 = "01mnlhz09hwdjaxwzjd6bql3fjb5zl9n8dzaxn7dvdxyhiiiihbw"; authors = [ "Ashley Mannix" "Dylan DPC" @@ -13647,7 +13712,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "visit" "visit-mut" "full" "extra-traits" ]; } { @@ -15197,7 +15262,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "fold" "visit" ]; } { @@ -15209,9 +15274,9 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.8.60"; + version = "0.8.62"; edition = "2021"; - sha256 = "1ghxkd4fv4ka88v2rg9260p6465v49hmc1zvqfm6yvs2nx5zq034"; + sha256 = "17asjqfdkqmxsx42myw1x5jlb28m5axlf9ifldqpbiy7dbsjnl46"; dependencies = [ { name = "zerocopy-derive"; @@ -15241,9 +15306,9 @@ rec { }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.8.60"; + version = "0.8.62"; edition = "2021"; - sha256 = "1nrlkb37wm1sq962725mxwhahaicbg277q25kbslvbavab3prhlr"; + sha256 = "06lx0gigf0j5pvp4dhlrv636b4mib37ijzlcc3i62rdhailj0msl"; procMacro = true; libName = "zerocopy_derive"; dependencies = [ @@ -15313,7 +15378,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "fold" "visit" ]; } { @@ -15325,9 +15390,9 @@ rec { }; "zeroize" = rec { crateName = "zeroize"; - version = "1.9.0"; + version = "1.9.1"; edition = "2024"; - sha256 = "0kpnij2v1ig6g2mhc0bnci0lrdfdhiq40afbc0fahajqc9jiag71"; + sha256 = "0yb8iykihpl3hfw5c4silw2lklpfxajkaa9yj1qw6jsy5hwq8c71"; authors = [ "The RustCrypto Project Developers" ]; @@ -15480,7 +15545,7 @@ rec { } { name = "syn"; - packageId = "syn 3.0.6"; + packageId = "syn 3.0.9"; features = [ "extra-traits" ]; } ]; diff --git a/extra/crds.yaml b/extra/crds.yaml index fe7d18a42..83287899a 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -2161,8 +2161,8 @@ spec: properties: secret: description: |- - A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), e.g. as a - Secret of type `kubernetes.io/tls`. + A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), e.g. as + a Secret of type `kubernetes.io/tls`. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 1dc977ea1..98eb8d541 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -65,8 +65,7 @@ use crate::{ update_status::update_status, }, crd::{ - APP_NAME, KAFKA_OPERATOR_NAME, KafkaPlatformAccessAuthentication, KafkaPodDescriptor, - MetadataManager, + APP_NAME, KAFKA_OPERATOR_NAME, KafkaPodDescriptor, MetadataManager, authorization::KafkaAuthorizationConfig, role::{AnyConfig, AnyConfigOverrides, KafkaRole}, v1alpha1, @@ -347,7 +346,7 @@ impl ValidatedClusterConfig { /// The configuration of the agent deployed with the cluster. pub struct ValidatedAgentConfig { pub image: String, - pub authentication: KafkaPlatformAccessAuthentication, + pub authentication: v1alpha1::KafkaPlatformAccessAuthentication, } /// Per-role configuration extracted during validation. diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index e9dc87ca9..bad1fb2a7 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -30,7 +30,7 @@ use crate::{ ValidatedAgentConfig, ValidatedCluster, build::{agent_selector, recommended_labels_for_agent_resources}, }, - crd::KafkaPlatformAccessAuthentication, + crd::v1alpha1::KafkaPlatformAccessAuthentication, }; constant!(AGENT_CONTAINER_NAME: ContainerName = "agent"); diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index b09942d88..8274f1b20 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -12,13 +12,12 @@ use serde::{Deserialize, Serialize}; use snafu::Snafu; use stackable_operator::{ commons::{ - cluster_operation::ClusterOperation, - networking::DomainName, - platform_access::{anonymous::Anonymous, tls::TlsClientCredential}, + cluster_operation::ClusterOperation, networking::DomainName, product_image_selection::ProductImage, }, config::merge::Merge, constant, + crd::platform_access::v1alpha1::{Anonymous, TlsClientCredential}, deep_merger::ObjectOverrides, kube::{CustomResource, runtime::reflector::ObjectRef}, role_utils::GenericRoleConfig, @@ -109,27 +108,6 @@ pub type ControllerRole = Role< JavaCommonConfig, >; -/// Access of the Stackable Data Platform to this Kafka cluster, used by an agent to manage resources -/// like `KafkaTopic`s. The credential must be authorized in Kafka by the user. -#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct KafkaPlatformAccess { - /// Whether the operator deploys the agent. False by default. - #[serde(default)] - pub enabled: bool, - - /// How the agent authenticates to Kafka. - pub authentication: KafkaPlatformAccessAuthentication, -} - -/// How the agent authenticates to Kafka. -#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub enum KafkaPlatformAccessAuthentication { - Tls(TlsClientCredential), - Anonymous(Anonymous), -} - #[versioned( version(name = "v1alpha1"), crates( @@ -172,7 +150,7 @@ pub mod versioned { /// Access of the Stackable Data Platform to this cluster. #[serde(default, skip_serializing_if = "Option::is_none")] - pub platform_access: Option, + pub platform_access: Option, // no doc - docs in ClusterOperation struct. #[serde(default)] @@ -183,6 +161,27 @@ pub mod versioned { pub object_overrides: ObjectOverrides, } + /// Access of the Stackable Data Platform to this Kafka cluster, used by an agent to manage + /// resources like `KafkaTopic`s. The credential must be authorized in Kafka by the user. + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct KafkaPlatformAccess { + /// Whether the operator deploys the agent. False by default. + #[serde(default)] + pub enabled: bool, + + /// How the agent authenticates to Kafka. + pub authentication: v1alpha1::KafkaPlatformAccessAuthentication, + } + + /// How the agent authenticates to Kafka. + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub enum KafkaPlatformAccessAuthentication { + Tls(TlsClientCredential), + Anonymous(Anonymous), + } + #[derive(Clone, Deserialize, Debug, Eq, JsonSchema, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct KafkaClusterConfig { From 773d3bdb83011bd1fa8f4fc63955d9848d257b99 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 21 Oct 2026 13:59:59 +0200 Subject: [PATCH 10/25] use the recreate strategy for the agent deployment --- .../src/controller/build/resource/agent.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index bad1fb2a7..7af6b6d39 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -12,7 +12,7 @@ use stackable_operator::{ constant, k8s_openapi::{ api::{ - apps::v1::{Deployment, DeploymentSpec}, + apps::v1::{Deployment, DeploymentSpec, DeploymentStrategy}, core::v1::{EnvVarSource, ObjectFieldSelector, ServiceAccount}, rbac::v1::{RoleBinding, RoleRef, Subject}, }, @@ -92,6 +92,11 @@ pub fn build_agent_deployment( metadata: agent_metadata(cluster), spec: Some(DeploymentSpec { replicas: Some(1), + // Never run two agents at the same time, as for the operator itself. + strategy: Some(DeploymentStrategy { + type_: Some("Recreate".to_owned()), + ..DeploymentStrategy::default() + }), selector: LabelSelector { match_labels: Some(agent_selector(cluster).into()), ..LabelSelector::default() @@ -210,6 +215,7 @@ mod tests { assert_eq!(deployment["metadata"]["name"], "simple-kafka-agent"); assert_eq!(deployment["spec"]["replicas"], 1); + assert_eq!(deployment["spec"]["strategy"]["type"], "Recreate"); // The selector must not match the broker or controller Pods. assert_eq!( deployment["spec"]["selector"]["matchLabels"], From 679a24a7b37ba08e55eb19138fb204ec0a855936 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 21 Oct 2026 14:16:02 +0200 Subject: [PATCH 11/25] ship agent binary in operator image --- .github/workflows/build.yaml | 42 ++--- .gitignore | 1 - Tiltfile | 17 +- default.nix | 36 +--- .../kafka-operator/templates/_helpers.tpl | 9 +- .../kafka-operator/templates/deployment.yaml | 8 - docker/Dockerfile | 2 +- docker/Dockerfile.agent | 158 ------------------ nix/meta.json | 2 +- result-agent | 1 + rust/operator-binary/src/controller.rs | 17 +- .../src/controller/build/resource/agent.rs | 13 +- .../src/controller/validate.rs | 67 +++++++- rust/operator-binary/src/crd/mod.rs | 9 - rust/operator-binary/src/main.rs | 13 +- 15 files changed, 106 insertions(+), 289 deletions(-) delete mode 100644 docker/Dockerfile.agent create mode 120000 result-agent diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2c6cc0009..7251f20b1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,22 +62,8 @@ jobs: - '**/Cargo.toml' - 'Cargo.lock' - '**/*.rs' - - 'nix/meta.json' - - # Operators that ship an agent (see `agent` in nix/meta.json) also build and publish its image. - - name: Determine Container Images - id: images - shell: bash - run: | - set -euo pipefail - IMAGES=$(jq -c --arg operator "$OPERATOR_NAME" ' - [{component: "operator", name: $operator, "container-file": "docker/Dockerfile"}] - + if .agent then [{component: "agent", name: .agent.name, "container-file": "docker/Dockerfile.agent"}] else [] end - ' nix/meta.json) - echo "IMAGES=$IMAGES" | tee -a "$GITHUB_OUTPUT" outputs: detected: ${{ steps.check.outputs.detected }} - images: ${{ steps.images.outputs.IMAGES }} helm-lint: name: Lint Helm Chart @@ -145,7 +131,7 @@ jobs: run: cargo udeps --workspace --all-targets build-container-image: - name: Build/Publish ${{ matrix.image.component }} ${{ matrix.runner.arch }} Image + name: Build/Publish ${{ matrix.runner.arch }} Image if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -160,7 +146,6 @@ jobs: runner: - { name: "ubuntu-latest", arch: "amd64" } - { name: "ubicloud-standard-8-arm", arch: "arm64" } - image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ${{ matrix.runner.name }} outputs: operator-version: ${{ steps.version.outputs.OPERATOR_VERSION }} @@ -223,10 +208,10 @@ jobs: id: build uses: stackabletech/actions/build-container-image@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-name: ${{ matrix.image.name }} + image-name: ${{ env.OPERATOR_NAME }} image-index-manifest-tag: ${{ steps.version.outputs.OPERATOR_VERSION }} build-arguments: VERSION=${{ steps.version.outputs.OPERATOR_VERSION }} - container-file: ${{ matrix.image.container-file }} + container-file: docker/Dockerfile - name: Publish Container Image to oci.stackable.tech if: ${{ !github.event.pull_request.head.repo.fork }} @@ -235,7 +220,7 @@ jobs: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build image-registry-password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: sdp/${{ matrix.image.name }} + image-repository: sdp/${{ env.OPERATOR_NAME }} canonical-image-manifest-tag: ${{ steps.build.outputs.image-manifest-tag }} canonical-source-image-uri: ${{ steps.build.outputs.image-manifest-uri }} @@ -246,12 +231,12 @@ jobs: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build image-registry-password: ${{ secrets.QUAY_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: stackable/sdp/${{ matrix.image.name }} + image-repository: stackable/sdp/${{ env.OPERATOR_NAME }} canonical-image-manifest-tag: ${{ steps.build.outputs.image-manifest-tag }} canonical-source-image-uri: ${{ steps.build.outputs.image-manifest-uri }} publish-index-manifest: - name: Publish/Sign ${{ matrix.image.component }} ${{ needs.build-container-image.outputs.operator-version }} Index + name: Publish/Sign ${{ needs.build-container-image.outputs.operator-version }} Index if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -263,10 +248,6 @@ jobs: permissions: contents: read id-token: write - strategy: - fail-fast: false - matrix: - image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ubuntu-latest steps: - name: Checkout Repository @@ -280,7 +261,7 @@ jobs: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build image-registry-password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: sdp/${{ matrix.image.name }} + image-repository: sdp/${{ env.OPERATOR_NAME }} canonical-image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} - name: Publish and Sign Image Index to quay.io @@ -289,7 +270,7 @@ jobs: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build image-registry-password: ${{ secrets.QUAY_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} - image-repository: stackable/sdp/${{ matrix.image.name }} + image-repository: stackable/sdp/${{ env.OPERATOR_NAME }} canonical-image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} publish-helm-chart: @@ -339,7 +320,7 @@ jobs: helm-version: v3.17.4 # This is currently the latest version which supports pushing to quay.io openshift-preflight-check: - name: Run OpenShift Preflight Check for ${{ matrix.image.component }} ${{ needs.build-container-image.outputs.operator-version }}-${{ matrix.arch }} + name: Run OpenShift Preflight Check for ${{ needs.build-container-image.outputs.operator-version }}-${{ matrix.arch }} if: | github.repository_owner == 'stackabletech' && (github.event_name != 'merge_group') @@ -355,19 +336,18 @@ jobs: arch: - amd64 - arm64 - image: ${{ fromJSON(needs.detect-changes.outputs.images) }} runs-on: ubuntu-latest steps: - name: Run OpenShift Preflight Check for oci.stackable.tech uses: stackabletech/actions/run-openshift-preflight@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-index-uri: oci.stackable.tech/sdp/${{ matrix.image.name }}:${{ needs.build-container-image.outputs.operator-version }} + image-index-uri: oci.stackable.tech/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} - name: Run OpenShift Preflight Check for quay.io uses: stackabletech/actions/run-openshift-preflight@34a64229959b15db6c5f307db8809805ba7edc55 # v0.18.3 with: - image-index-uri: quay.io/stackable/sdp/${{ matrix.image.name }}:${{ needs.build-container-image.outputs.operator-version }} + image-index-uri: quay.io/stackable/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} # This job is a required check in GitHub Settings for this repository. diff --git a/.gitignore b/.gitignore index cc2e5c12e..411cc85da 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ target/ *.tgz result -result-agent image.tar tilt_options.json diff --git a/Tiltfile b/Tiltfile index fba0c44f2..1769d19a5 100644 --- a/Tiltfile +++ b/Tiltfile @@ -34,22 +34,7 @@ custom_build( # We need to set the correct image annotation on the operator Deployment to use e.g. # oci.stackable.tech/sandbox/opa-operator:7y19m3d8clwxlv34v5q2x4p7v536s00g instead of # oci.stackable.tech/sandbox/opa-operator:0.0.0-dev (which does not exist) -deployment_image_json_paths = ['{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}'] - -# Operators that ship an agent (see `agent` in nix/meta.json) also build the agent image and pass -# it to the operator via the `internal.stackable.tech/agent-image` annotation. -if 'agent' in meta: - agent_image_name = operator_repository + '/' + meta['agent']['name'] - custom_build( - agent_image_name, - 'nix-build . -A dockerAgent --argstr dockerNameAgent "' + agent_image_name + '" -o result-agent && ./result-agent/load-image | docker load', - deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', "nix", 'build.rs', 'vendor'], - ignore=['*.~undo-tree~'], - outputs_image_ref_to='result-agent/ref', - ) - deployment_image_json_paths.append('{.spec.template.metadata.annotations.internal\\.stackable\\.tech/agent-image}') - -k8s_kind('Deployment', image_json_path=deployment_image_json_paths) +k8s_kind('Deployment', image_json_path='{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}') k8s_kind('DaemonSet', image_json_path='{.spec.template.metadata.annotations.internal\\.stackable\\.tech/image}') # Optionally specify a custom Helm values file to be passed to the Helm deployment below. diff --git a/default.nix b/default.nix index abaa026b6..6feb190a3 100644 --- a/default.nix +++ b/default.nix @@ -101,8 +101,6 @@ } , meta ? pkgsLocal.lib.importJSON ./nix/meta.json , dockerName ? "oci.stackable.tech/sandbox/${meta.operator.name}" -# Only used by operators that ship an agent (see `agent` in nix/meta.json) -, dockerNameAgent ? "oci.stackable.tech/sandbox/${meta.agent.name}" , dockerTag ? null # Controls the amount of debug information included in the built operator binaries, # see https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo @@ -127,11 +125,7 @@ rec { inherit cargo sources pkgsLocal pkgsTarget meta; inherit (pkgsLocal) lib; pkgs = lib.warn "pkgs is not cross-compilation-aware, explicitly use either pkgsLocal or pkgsTarget" pkgsLocal; - # Operators that ship an agent (see `agent` in nix/meta.json) keep the agent binary out of the - # operator image, as it has its own image (`dockerAgent`). - build = if meta ? agent - then cargo.workspaceMembers."stackable-${meta.operator.name}".build - else cargo.allWorkspaceMembers; + build = cargo.allWorkspaceMembers; entrypoint = build+"/bin/stackable-${meta.operator.name}"; # Run crds in the target environment, to avoid compiling everything twice crds = pkgsTarget.runCommand "${meta.operator.name}-crds.yaml" {} @@ -149,13 +143,13 @@ rec { # build it in the local environment so that the generated load-image # can run locally. # That's still fine, as long as we only refer to pkgsTarget *inside* of the image. - dockerImageArgs = { + dockerImage = pkgsLocal.dockerTools.streamLayeredImage { name = dockerName; tag = dockerTag; contents = [ # Kerberos 5 must be installed globally to load plugins correctly pkgsTarget.krb5 - # Make the operator binaries available on $PATH + # Make the whole cargo workspace available on $PATH build ] ++ lib.optional includeShell [ pkgsTarget.bashInteractive @@ -195,7 +189,6 @@ rec { User = toString stackableUserUid; }; }; - dockerImage = pkgsLocal.dockerTools.streamLayeredImage dockerImageArgs; docker = pkgsLocal.linkFarm "${dockerImage.name}-docker" [ { name = "load-image"; @@ -219,29 +212,6 @@ rec { } ]; - # The image of the agent, only built for operators that ship one. - dockerAgent = if meta ? agent then - let - agentBuild = cargo.workspaceMembers."stackable-${meta.agent.name}".build; - agentImage = pkgsLocal.dockerTools.streamLayeredImage (dockerImageArgs // { - name = dockerNameAgent; - contents = [ agentBuild ] ++ lib.optional includeShell [ - pkgsTarget.bashInteractive - pkgsTarget.coreutils - pkgsTarget.util-linuxMinimal - ]; - config = dockerImageArgs.config // { - Entrypoint = [ "${agentBuild}/bin/stackable-${meta.agent.name}" ]; - }; - }); - in pkgsLocal.linkFarm "${agentImage.name}-docker" [ - { name = "load-image"; path = agentImage; } - { name = "ref"; path = pkgsLocal.writeText "${agentImage.name}-image-tag" "${agentImage.imageName}:${agentImage.imageTag}"; } - { name = "image-repo"; path = pkgsLocal.writeText "${agentImage.name}-repo" agentImage.imageName; } - { name = "image-tag"; path = pkgsLocal.writeText "${agentImage.name}-tag" agentImage.imageTag; } - ] - else null; - # need to use vendored crate2nix because of https://github.com/kolloch/crate2nix/issues/264 crate2nix = import sources.crate2nix { pkgs = pkgsLocal; }; tilt = pkgsLocal.tilt; diff --git a/deploy/helm/kafka-operator/templates/_helpers.tpl b/deploy/helm/kafka-operator/templates/_helpers.tpl index 281aa5495..6f6d19411 100644 --- a/deploy/helm/kafka-operator/templates/_helpers.tpl +++ b/deploy/helm/kafka-operator/templates/_helpers.tpl @@ -7,7 +7,7 @@ Expand the name of the chart. {{/* Fixed product name. Unlike kafka-operator.name it ignores nameOverride, because it must match -names hardcoded in the operator and the published image names. +names hardcoded in the operator. */}} {{- define "kafka-operator.productName" -}} kafka @@ -92,10 +92,3 @@ Build the full operator container image reference. {{- define "kafka-operator.image" -}} {{- printf "%s/%s:%s" .Values.image.repository .Chart.Name (.Values.image.tag | default .Chart.AppVersion) -}} {{- end }} - -{{/* -Build the full agent container image reference. The agent is released together with the operator. -*/}} -{{- define "kafka-operator.agentImage" -}} -{{- printf "%s/%s-agent:%s" .Values.image.repository (include "kafka-operator.productName" .) (.Values.image.tag | default .Chart.AppVersion) -}} -{{- end }} diff --git a/deploy/helm/kafka-operator/templates/deployment.yaml b/deploy/helm/kafka-operator/templates/deployment.yaml index 9fac4f33b..6f7163dcd 100644 --- a/deploy/helm/kafka-operator/templates/deployment.yaml +++ b/deploy/helm/kafka-operator/templates/deployment.yaml @@ -16,7 +16,6 @@ spec: metadata: annotations: internal.stackable.tech/image: {{ include "kafka-operator.image" . }} - internal.stackable.tech/agent-image: {{ include "kafka-operator.agentImage" . }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -71,13 +70,6 @@ spec: - name: IMAGE_REPOSITORY value: {{ .Values.image.productRepository | default .Values.image.repository }} - # The image of the agent the operator deploys alongside a cluster. - - name: AGENT_IMAGE - # Tilt can use annotations as image paths, but not env variables - valueFrom: - fieldRef: - fieldPath: metadata.annotations['internal.stackable.tech/agent-image'] - # Operators need to know the node name they are running on, to e.g. discover the # Kubernetes domain name from the kubelet API. - name: KUBERNETES_NODE_NAME diff --git a/docker/Dockerfile b/docker/Dockerfile index a96fc6111..84458c3a2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -190,7 +190,7 @@ EOF COPY LICENSE /licenses/LICENSE -COPY --from=builder --chown=${STACKABLE_USER_UID}:0 /app/stackable-kafka-operator* /app/stackable-src.tar.gz /usr/local/bin/ +COPY --from=builder --chown=${STACKABLE_USER_UID}:0 /app/* /usr/local/bin/ USER ${STACKABLE_USER_UID} diff --git a/docker/Dockerfile.agent b/docker/Dockerfile.agent deleted file mode 100644 index 04f55b38d..000000000 --- a/docker/Dockerfile.agent +++ /dev/null @@ -1,158 +0,0 @@ -# syntax=docker/dockerfile:1.16.0@sha256:e2dd261f92e4b763d789984f6eab84be66ab4f5f08052316d8eb8f173593acf7 -# NOTE: The syntax directive needs to be the first line in a Dockerfile -# Find the latest versions here: https://hub.docker.com/r/docker/dockerfile/tags -# And the changelogs: https://docs.docker.com/build/buildkit/dockerfile-release-notes/ or https://github.com/moby/buildkit/releases - -# https://docs.docker.com/build/checks/#fail-build-on-check-violations -# check=error=true - -# We want to automatically use the latest. We also don't tag our images with a version. -# hadolint ignore=DL3007 -FROM oci.stackable.tech/sdp/ubi10-rust-builder:latest AS builder - - -# We want to automatically use the latest. -# hadolint ignore=DL3007 -FROM registry.access.redhat.com/ubi10/ubi-minimal:latest AS agent - -ARG VERSION -# NOTE (@Techassi): This is required for OpenShift/Red Hat certification -# Keeping this as "1" seems to be fine since a couple of years /shrug -ARG RELEASE="1" - -# These are chosen at random and are this high on purpose to have very little chance to clash with an existing user or group on the host system -# NOTE: Please also update default.nix accordingly! -ARG STACKABLE_USER_GID="574654813" -ARG STACKABLE_USER_UID="782252253" -ARG STACKABLE_USER_NAME="stackable" - -# Sets the default shell to Bash with strict error handling and robust pipeline processing. -# "-e": Exits immediately if a command exits with a non-zero status -# "-u": Treats unset variables as an error, preventing unexpected behavior from undefined variables. -# "-o pipefail": Causes a pipeline to return the exit status of the last command in the pipe that failed, ensuring errors in any part of a pipeline are not ignored. -# "-c": Allows the execution of commands passed as a string -SHELL ["/bin/bash", "-euo", "pipefail", "-c"] - -# These labels have mostly been superseded by the OpenContainer spec annotations below but it doesn't hurt to include them -# http://label-schema.org/rc1/ -LABEL name="Stackable Agent for Apache Kafka" -LABEL maintainer="info@stackable.tech" -LABEL vendor="Stackable GmbH" -LABEL version="${VERSION}" -LABEL release="${RELEASE}" -LABEL summary="Manage resources inside Apache Kafka clusters." -LABEL description="Manage resources inside Apache Kafka clusters." - -# Overwriting/Pinning UBI labels -# https://github.com/projectatomic/ContainerApplicationGenericLabels -LABEL vcs-ref="" -LABEL distribution-scope="public" -LABEL url="https://stackable.tech" -ARG TARGETARCH -LABEL architecture="${TARGETARCH}" -LABEL com.redhat.component="" -# It complains about it being an invalid label but RedHat uses it and we want to override it and it works.... -# hadolint ignore=DL3048 -LABEL com.redhat.license_terms="" -LABEL io.buildah.version="" -LABEL io.openshift.expose-services="" - -# https://github.com/opencontainers/image-spec/blob/64294bd7a2bf2537e1a6a34d687caae70300b0c4/annotations.md#annotations -LABEL org.opencontainers.image.authors="info@stackable.tech" -LABEL org.opencontainers.image.url="https://stackable.tech" -LABEL org.opencontainers.image.vendor="Stackable GmbH" -LABEL org.opencontainers.image.licenses="OSL-3.0" -LABEL org.opencontainers.image.documentation="https://docs.stackable.tech/home/stable/kafka/" -LABEL org.opencontainers.image.version="${VERSION}" -LABEL org.opencontainers.image.revision="${RELEASE}" -LABEL org.opencontainers.image.title="Stackable Agent for Apache Kafka" -LABEL org.opencontainers.image.description="Manage resources inside Apache Kafka clusters." - -# https://docs.openshift.com/container-platform/4.16/openshift_images/create-images.html#defining-image-metadata -# https://github.com/projectatomic/ContainerApplicationGenericLabels/blob/master/vendor/redhat/labels.md -LABEL io.openshift.tags="ubi10,stackable,sdp,kafka" -LABEL io.k8s.description="Manage resources inside Apache Kafka clusters." -LABEL io.k8s.display-name="Stackable Agent for Apache Kafka" - -COPY <> /stackable/.bashrc - -echo -e "if [ -f ~/.bashrc ]; then\n\tsource ~/.bashrc\nfi" >> /stackable/.profile - -chown ${STACKABLE_USER_UID}:0 /stackable/.bashrc -chown ${STACKABLE_USER_UID}:0 /stackable/.profile - -# All files and folders owned by root to support running as arbitrary users -# This is best practice as all container users will belong to the root group (0) -chown -R ${STACKABLE_USER_UID}:0 /stackable -chmod -R g=u /stackable -EOF - -COPY <, } #[derive(Snafu, Debug, EnumDiscriminants)] @@ -481,7 +481,7 @@ pub async fn reconcile_kafka( kafka, dereferenced_objects, &ctx.operator_environment, - &ctx.agent_image, + ctx.operator_image.as_deref(), ) .context(ValidateClusterSnafu)?; @@ -541,6 +541,8 @@ pub(crate) mod test_support { use super::{ValidatedCluster, dereference::DereferencedObjects, validate::validate}; use crate::crd::{authentication::ResolvedAuthenticationClasses, v1alpha1}; + pub const OPERATOR_IMAGE: &str = "oci.stackable.tech/sdp/kafka-operator:0.0.0-dev"; + /// The expected `app.kubernetes.io/version` label value for the given product version. /// /// The `-stackable` suffix carries the operator's own version, which is `0.0.0-dev` on main @@ -633,6 +635,13 @@ pub(crate) mod test_support { /// the result. Used for tests asserting on a specific validation failure. pub fn validate_err( kafka: &v1alpha1::KafkaCluster, + ) -> Result { + validate_with_operator_image(kafka, Some(OPERATOR_IMAGE)) + } + + pub fn validate_with_operator_image( + kafka: &v1alpha1::KafkaCluster, + operator_image: Option<&str>, ) -> Result { validate( kafka, @@ -643,7 +652,7 @@ pub(crate) mod test_support { bootstrap_listeners: Vec::new(), }, &operator_environment(), - &crate::crd::default_agent_image(&operator_environment().image_repository), + operator_image, ) } } @@ -796,7 +805,7 @@ spec: {} operator_service_name: "kafka-operator".to_owned(), image_repository: "oci.stackable.tech/sdp".to_owned(), }, - agent_image: crate::crd::default_agent_image("oci.stackable.tech/sdp"), + operator_image: None, }); reconcile_kafka(Arc::new(kafka), ctx).await diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 7af6b6d39..fe677e317 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -52,6 +52,7 @@ pub fn build_agent_deployment( cb_agent .image(&agent_config.image) + .command(vec!["stackable-kafka-agent".to_owned()]) .args(vec!["run".to_owned()]) .add_env_var_from_source( "KUBERNETES_NODE_NAME", @@ -153,9 +154,8 @@ mod tests { use serde_json::{Value, json}; use super::*; - use crate::{ - controller::test_support::{app_version_label, minimal_kafka, validated_cluster}, - crd::default_agent_image, + use crate::controller::test_support::{ + OPERATOR_IMAGE, app_version_label, minimal_kafka, validated_cluster, }; fn cluster(platform_access: &str) -> ValidatedCluster { @@ -205,7 +205,7 @@ mod tests { let cluster = cluster("{enabled: true, authentication: {tls: {secretClass: tls}}}"); let agent_config = cluster.agent_config.expect("platform access is enabled"); - assert_eq!(agent_config.image, default_agent_image("oci.example.org")); + assert_eq!(agent_config.image, OPERATOR_IMAGE); } #[test] @@ -239,9 +239,10 @@ mod tests { let pod_spec = &deployment["spec"]["template"]["spec"]; assert_eq!(pod_spec["serviceAccountName"], "simple-kafka-agent"); + assert_eq!(pod_spec["containers"][0]["image"], OPERATOR_IMAGE); assert_eq!( - pod_spec["containers"][0]["image"], - default_agent_image("oci.example.org") + pod_spec["containers"][0]["command"], + json!(["stackable-kafka-agent"]) ); assert_eq!(pod_spec["containers"][0]["args"], json!(["run"])); assert_eq!( diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index 62fb2bff8..9865afeca 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -115,6 +115,12 @@ pub enum Error { to join without it" ))] MissingKraftControllerRole, + + #[snafu(display( + "platform access requires the operator image, which also contains the agent; set the \ + OPERATOR_IMAGE environment variable of the operator" + ))] + PlatformAccessRequiresOperatorImage, } /// Validated logging configuration for a Kafka role group's Kafka and (optional) Vector @@ -199,7 +205,7 @@ pub fn validate( kafka: &v1alpha1::KafkaCluster, dereferenced_objects: DereferencedObjects, operator_environment: &OperatorEnvironmentOptions, - agent_image: &str, + operator_image: Option<&str>, ) -> Result { let image = kafka .spec @@ -339,10 +345,15 @@ pub fn validate( .platform_access .as_ref() .filter(|platform_access| platform_access.enabled) - .map(|platform_access| ValidatedAgentConfig { - image: agent_image.to_owned(), - authentication: platform_access.authentication.clone(), - }); + .map(|platform_access| { + Ok(ValidatedAgentConfig { + image: operator_image + .context(PlatformAccessRequiresOperatorImageSnafu)? + .to_owned(), + authentication: platform_access.authentication.clone(), + }) + }) + .transpose()?; Ok(ValidatedCluster::new( name, @@ -462,7 +473,9 @@ mod tests { use super::{Error, KAFKA_CLUSTER_ID, inject_cluster_id}; use crate::{ - controller::test_support::{app_version_label, minimal_kafka, validated_cluster}, + controller::test_support::{ + app_version_label, minimal_kafka, validate_with_operator_image, validated_cluster, + }, crd::role::KafkaRole, }; @@ -564,6 +577,48 @@ mod tests { } } + #[rstest::rstest] + #[case::enabled(true, false)] + #[case::disabled(false, true)] + fn platform_access_requires_the_operator_image(#[case] enabled: bool, #[case] valid: bool) { + let kafka = minimal_kafka(&format!( + r#" + apiVersion: kafka.stackable.tech/v1alpha1 + kind: KafkaCluster + metadata: + name: simple-kafka + namespace: default + uid: 12345678-1234-1234-1234-123456789012 + spec: + image: + productVersion: 3.9.2 + clusterConfig: + zookeeperConfigMapName: xyz + platformAccess: + enabled: {enabled} + authentication: + tls: + secretClass: tls + brokers: + roleGroups: + default: + replicas: 1 + "# + )); + + let result = validate_with_operator_image(&kafka, None); + + if valid { + assert!(result.is_ok(), "expected Ok, got: {:?}", result.err()); + } else { + assert!( + matches!(result, Err(Error::PlatformAccessRequiresOperatorImage)), + "expected PlatformAccessRequiresOperatorImage, got: {:?}", + result.err() + ); + } + } + #[test] fn injects_cluster_id_when_absent() { let env = inject_cluster_id(EnvVarSet::new(), Some("my-id")); diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 8274f1b20..840fdc175 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -46,15 +46,6 @@ use crate::crd::{ }; pub const CONTAINER_IMAGE_BASE_NAME: &str = "kafka"; -pub const AGENT_IMAGE_BASE_NAME: &str = "kafka-agent"; - -/// The agent image of the same release as the operator. -pub fn default_agent_image(image_repository: &str) -> String { - format!( - "{image_repository}/{AGENT_IMAGE_BASE_NAME}:{}", - crate::built_info::PKG_VERSION - ) -} pub const APP_NAME: &str = "kafka"; pub const KAFKA_OPERATOR_NAME: &str = "kafka.stackable.tech"; pub const FIELD_MANAGER: &str = "kafka-operator"; diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 809bd5664..eb28ac0f4 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -37,7 +37,7 @@ use stackable_operator::{ use crate::{ controller::KAFKA_FULL_CONTROLLER_NAME, - crd::{KAFKA_OPERATOR_NAME, KafkaCluster, KafkaClusterVersion, default_agent_image, v1alpha1}, + crd::{KAFKA_OPERATOR_NAME, KafkaCluster, KafkaClusterVersion, v1alpha1}, webhooks::conversion::create_webhook_server, }; @@ -68,9 +68,10 @@ struct KafkaRun { #[clap(flatten)] common: RunArguments, - /// The agent image. Defaults to the agent image belonging to this operator release. + /// The image of this operator, which also contains the agent. Required to enable platform + /// access on a KafkaCluster. #[arg(long, env)] - agent_image: Option, + operator_image: Option, } #[tokio::main] @@ -87,7 +88,7 @@ async fn main() -> anyhow::Result<()> { maintenance, common, }, - agent_image, + operator_image, }) => { // NOTE (@NickLarsenNZ): Before stackable-telemetry was used: // - The console log level was set by `KAFKA_OPERATOR_LOG`, and is now `CONSOLE_LOG` (when using Tracing::pre_configured). @@ -196,10 +197,8 @@ async fn main() -> anyhow::Result<()> { controller::error_policy, Arc::new(controller::Ctx { client: client.clone(), - agent_image: agent_image.unwrap_or_else(|| { - default_agent_image(&operator_environment.image_repository) - }), operator_environment, + operator_image, }), ) // We can let the reporting happen in the background From 85716c905bd6c38f8d91bb20b1a3d01d97d6ed9b Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 21 Oct 2026 15:12:41 +0200 Subject: [PATCH 12/25] cleanup & only watch deployments with agent labels --- .../kafka-operator/templates/_helpers.tpl | 8 ---- .../templates/clusterrole-agent.yaml | 2 +- .../templates/clusterrole-operator.yaml | 2 +- result-agent | 1 - .../src/controller/build/mod.rs | 2 +- .../src/controller/build/resource/agent.rs | 37 +++++++++---------- .../src/controller/validate.rs | 12 +++--- rust/operator-binary/src/main.rs | 4 +- 8 files changed, 29 insertions(+), 39 deletions(-) delete mode 120000 result-agent diff --git a/deploy/helm/kafka-operator/templates/_helpers.tpl b/deploy/helm/kafka-operator/templates/_helpers.tpl index 6f6d19411..9c61cd511 100644 --- a/deploy/helm/kafka-operator/templates/_helpers.tpl +++ b/deploy/helm/kafka-operator/templates/_helpers.tpl @@ -5,14 +5,6 @@ Expand the name of the chart. {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-operator" }} {{- end }} -{{/* -Fixed product name. Unlike kafka-operator.name it ignores nameOverride, because it must match -names hardcoded in the operator. -*/}} -{{- define "kafka-operator.productName" -}} -kafka -{{- end }} - {{/* Expand the name of the chart. */}} diff --git a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml index a17015062..8288ab33a 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml @@ -4,7 +4,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: {{ include "kafka-operator.productName" . }}-agent-clusterrole + name: {{ include "kafka-operator.name" . }}-agent-clusterrole labels: {{- include "kafka-operator.labels" . | nindent 4 }} rules: diff --git a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml index cabc631e4..96045367c 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml @@ -50,7 +50,7 @@ rules: - bind resourceNames: - {{ include "kafka-operator.name" . }}-clusterrole - - {{ include "kafka-operator.productName" . }}-agent-clusterrole + - {{ include "kafka-operator.name" . }}-agent-clusterrole # StatefulSet created per role group (broker, KRaft controller). Applied via # SSA, tracked for orphan cleanup, and owned by the controller. - apiGroups: diff --git a/result-agent b/result-agent deleted file mode 120000 index 9ac2d309c..000000000 --- a/result-agent +++ /dev/null @@ -1 +0,0 @@ -/nix/store/6m2nq8gfixyb147i629qrj894b3bxazv-stream-kafka-agent-docker \ No newline at end of file diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index 45764219d..8ddcf577e 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -239,11 +239,11 @@ pub(crate) fn recommended_labels_for_unversioned_role_group_resources( ) } -/// Selector labels matching the pods of a role group. pub(crate) fn agent_selector(cluster: &ValidatedCluster) -> Labels { label::agent_selector(&cluster.name, &PRODUCT_NAME) } +/// Selector labels matching the pods of a role group. pub(crate) fn role_group_selector( cluster: &ValidatedCluster, role_name: &RoleName, diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index ac9bec6e8..8e09b28ab 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -11,10 +11,11 @@ use stackable_operator::{ }, constant, k8s_openapi::{ + Resource, api::{ apps::v1::{Deployment, DeploymentSpec, DeploymentStrategy}, core::v1::{EnvVarSource, ObjectFieldSelector, ServiceAccount}, - rbac::v1::{RoleBinding, RoleRef, Subject}, + rbac::v1::{ClusterRole, RoleBinding, RoleRef, Subject}, }, apimachinery::pkg::apis::meta::v1::LabelSelector, }, @@ -121,12 +122,12 @@ pub fn build_agent_role_binding(cluster: &ValidatedCluster) -> RoleBinding { RoleBinding { metadata: agent_metadata(cluster), role_ref: RoleRef { - api_group: Some("rbac.authorization.k8s.io".to_owned()), - kind: "ClusterRole".to_owned(), + api_group: Some(ClusterRole::GROUP.to_owned()), + kind: ClusterRole::KIND.to_owned(), name: AGENT_CLUSTER_ROLE_NAME.to_owned(), }, subjects: Some(vec![Subject { - kind: "ServiceAccount".to_owned(), + kind: ServiceAccount::KIND.to_owned(), name: agent_name(cluster), namespace: Some(cluster.namespace.to_string()), ..Subject::default() @@ -185,13 +186,12 @@ mod tests { validated_cluster(&kafka) } - fn agent_deployment(platform_access: &str) -> Value { - let cluster = cluster(platform_access); + fn agent_deployment(cluster: &ValidatedCluster) -> Value { let agent_config = cluster .agent_config .as_ref() .expect("platform access is enabled"); - serde_json::to_value(build_agent_deployment(&cluster, agent_config)) + serde_json::to_value(build_agent_deployment(cluster, agent_config)) .expect("must be serializable") } @@ -210,8 +210,9 @@ mod tests { #[test] fn test_deployment() { - let deployment = - agent_deployment("{enabled: true, authentication: {tls: {secretClass: tls}}}"); + let deployment = agent_deployment(&cluster( + "{enabled: true, authentication: {tls: {secretClass: tls}}}", + )); assert_eq!(deployment["metadata"]["name"], "simple-kafka-agent"); assert_eq!(deployment["spec"]["replicas"], 1); @@ -258,8 +259,9 @@ mod tests { #[test] fn test_deployment_with_static_secret() { - let deployment = - agent_deployment("{enabled: true, authentication: {tls: {secret: my-cert}}}"); + let deployment = agent_deployment(&cluster( + "{enabled: true, authentication: {tls: {secret: my-cert}}}", + )); assert_eq!( deployment["spec"]["template"]["spec"]["volumes"], @@ -269,7 +271,8 @@ mod tests { #[test] fn deployment_with_anonymous_authentication_mounts_no_credential() { - let deployment = agent_deployment("{enabled: true, authentication: {anonymous: {}}}"); + let deployment = + agent_deployment(&cluster("{enabled: true, authentication: {anonymous: {}}}")); let pod_spec = &deployment["spec"]["template"]["spec"]; assert_eq!(pod_spec["volumes"], Value::Null); @@ -278,16 +281,10 @@ mod tests { #[test] fn test_deployment_uses_product_image_pull_secrets() { - let cluster = cluster_with_image( + let deployment = agent_deployment(&cluster_with_image( "{productVersion: 3.9.2, pullSecrets: [{name: regcred}]}", "{enabled: true, authentication: {tls: {secretClass: tls}}}", - ); - let agent_config = cluster - .agent_config - .as_ref() - .expect("platform access is enabled"); - let deployment = serde_json::to_value(build_agent_deployment(&cluster, agent_config)) - .expect("must be serializable"); + )); assert_eq!( deployment["spec"]["template"]["spec"]["imagePullSecrets"], diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index 8ca80138d..2a2dabd26 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -582,9 +582,9 @@ mod tests { } #[rstest::rstest] - #[case::enabled(true, false)] - #[case::disabled(false, true)] - fn platform_access_requires_the_operator_image(#[case] enabled: bool, #[case] valid: bool) { + #[case::enabled(true)] + #[case::disabled(false)] + fn platform_access_requires_the_operator_image(#[case] enabled: bool) { let kafka = minimal_kafka(&format!( r#" apiVersion: kafka.stackable.tech/v1alpha1 @@ -612,14 +612,14 @@ mod tests { let result = validate_with_operator_image(&kafka, None); - if valid { - assert!(result.is_ok(), "expected Ok, got: {:?}", result.err()); - } else { + if enabled { assert!( matches!(result, Err(Error::PlatformAccessRequiresOperatorImage)), "expected PlatformAccessRequiresOperatorImage, got: {:?}", result.err() ); + } else { + assert!(result.is_ok(), "expected Ok, got: {:?}", result.err()); } } diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index a24f5df5e..817b07ac1 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -186,7 +186,9 @@ async fn main() -> anyhow::Result<()> { ) .owns( watch_namespace.get_api::>(&client), - watcher::Config::default(), + // The agent is a the only Deployment + watcher::Config::default() + .labels("app.kubernetes.io/name=kafka,app.kubernetes.io/component=agent"), ) .watches( watch_namespace.get_api::>(&client), From 146602d939e09339b1f3d5f3dae9fc0f38ec12a7 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Fri, 23 Oct 2026 18:20:12 +0200 Subject: [PATCH 13/25] set fsGroup on the agent pod so it can read secret-operator volumes --- .../src/controller/build/resource/agent.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 8e09b28ab..c22ebc625 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -88,7 +88,11 @@ pub fn build_agent_deployment( .image_pull_secrets_from_product_image(&cluster.image) .add_container(cb_agent.build()) .service_account_name(agent_name(cluster)) - .security_context(PodSecurityContextBuilder::with_stackable_defaults().build()); + .security_context( + PodSecurityContextBuilder::with_stackable_defaults() + .fs_group(1000) + .build(), + ); Deployment { metadata: agent_metadata(cluster), @@ -217,6 +221,11 @@ mod tests { assert_eq!(deployment["metadata"]["name"], "simple-kafka-agent"); assert_eq!(deployment["spec"]["replicas"], 1); assert_eq!(deployment["spec"]["strategy"]["type"], "Recreate"); + // secret-operator volumes are only readable by the fsGroup. + assert_eq!( + deployment["spec"]["template"]["spec"]["securityContext"]["fsGroup"], + 1000 + ); // The selector must not match the broker or controller Pods. assert_eq!( deployment["spec"]["selector"]["matchLabels"], From 60f012398538c12828d6701c05800d6faafc5d10 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Fri, 23 Oct 2026 20:17:19 +0200 Subject: [PATCH 14/25] align CRD and validation with operator-rs and decision outcome --- Cargo.lock | 71 ++++--- Cargo.nix | 144 ++++++------- crate-hashes.json | 10 +- .../templates/clusterrole-agent.yaml | 2 +- .../templates/clusterrole-operator.yaml | 2 +- extra/crds.yaml | 100 ++++----- rust/operator-binary/src/controller.rs | 86 +++++++- .../src/controller/build/mod.rs | 2 +- .../src/controller/build/resource/agent.rs | 72 ++++--- .../src/controller/validate.rs | 194 +++++++++++++++--- rust/operator-binary/src/crd/mod.rs | 59 +++--- rust/operator-binary/src/main.rs | 7 +- 12 files changed, 501 insertions(+), 248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab828f1eb..42c5394f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1711,8 +1711,8 @@ dependencies = [ [[package]] name = "k8s-version" -version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +version = "0.1.4" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "darling 0.24.1", "regex", @@ -1876,6 +1876,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libyaml-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e126dda6f34391ab7b444f9922055facc83c07a910da3eb16f1e4d9c45dc777" + [[package]] name = "libz-sys" version = "1.1.30" @@ -2994,19 +3000,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "sha1" version = "0.10.7" @@ -3175,7 +3168,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "const-oid", "ecdsa", @@ -3231,8 +3224,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.119.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +version = "0.121.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "base64 0.23.1", "clap", @@ -3255,7 +3248,6 @@ dependencies = [ "semver", "serde", "serde_json", - "serde_yaml", "sha2", "snafu 0.9.2", "stackable-operator-derive", @@ -3271,12 +3263,13 @@ dependencies = [ "url", "uuid", "xml", + "yaml_serde", ] [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3286,8 +3279,8 @@ dependencies = [ [[package]] name = "stackable-shared" -version = "0.1.2" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +version = "0.2.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "jiff", "k8s-openapi", @@ -3295,16 +3288,16 @@ dependencies = [ "schemars", "semver", "serde", - "serde_yaml", "snafu 0.9.2", "strum", "time", + "yaml_serde", ] [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "axum", "clap", @@ -3327,22 +3320,21 @@ dependencies = [ [[package]] name = "stackable-versioned" -version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +version = "0.13.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "kube", "schemars", "serde", "serde_json", - "serde_yaml", "snafu 0.9.2", "stackable-versioned-macros", ] [[package]] name = "stackable-versioned-macros" -version = "0.11.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +version = "0.13.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "convert_case", "darling 0.24.1", @@ -3359,7 +3351,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#92e1a3655432e3899da735a9d86ded2e38030c0e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" dependencies = [ "arc-swap", "async-trait", @@ -3961,12 +3953,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.9.0" @@ -4336,6 +4322,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f45bb2c13fec6a6cb4c0f76a7e94839e110a14ec803ec2940777a94c347bc52" +[[package]] +name = "yaml_serde" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b729a08a9a6be689bbad3e2bf8015926db54b6622cc89c3a5f7dc174b9e918" +dependencies = [ + "indexmap", + "itoa", + "libyaml-rs", + "ryu", + "serde", +] + [[package]] name = "yoke" version = "0.8.3" diff --git a/Cargo.nix b/Cargo.nix index ff21a3b66..7b49d7c1a 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5440,12 +5440,12 @@ rec { }; "k8s-version" = rec { crateName = "k8s-version"; - version = "0.1.3"; + version = "0.1.4"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -6177,6 +6177,19 @@ rec { }; resolvedDefaultFeatures = [ "arch" "default" ]; }; + "libyaml-rs" = rec { + crateName = "libyaml-rs"; + version = "0.3.0"; + edition = "2021"; + crateBin = []; + sha256 = "0xy7bp2dkr7i2vms63cigb087k7salh95ya4njvilf9ldzd6s4if"; + libName = "libyaml_rs"; + authors = [ + "David Tolnay " + "YAML Organization " + ]; + + }; "libz-sys" = rec { crateName = "libz-sys"; version = "1.1.30"; @@ -9885,38 +9898,6 @@ rec { } ]; - }; - "serde_yaml" = rec { - crateName = "serde_yaml"; - version = "0.9.34+deprecated"; - edition = "2021"; - sha256 = "0isba1fjyg3l6rxk156k600ilzr8fp7crv82rhal0rxz5qd1m2va"; - authors = [ - "David Tolnay " - ]; - dependencies = [ - { - name = "indexmap"; - packageId = "indexmap"; - } - { - name = "itoa"; - packageId = "itoa"; - } - { - name = "ryu"; - packageId = "ryu"; - } - { - name = "serde"; - packageId = "serde"; - } - { - name = "unsafe-libyaml"; - packageId = "unsafe-libyaml"; - } - ]; - }; "sha1" = rec { crateName = "sha1"; @@ -10397,7 +10378,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10631,12 +10612,12 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.119.0"; + version = "0.121.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10739,10 +10720,6 @@ rec { name = "serde_json"; packageId = "serde_json"; } - { - name = "serde_yaml"; - packageId = "serde_yaml"; - } { name = "sha2"; packageId = "sha2"; @@ -10812,6 +10789,10 @@ rec { name = "xml"; packageId = "xml"; } + { + name = "yaml_serde"; + packageId = "yaml_serde"; + } ]; features = { "certs" = [ "dep:stackable-certs" ]; @@ -10835,7 +10816,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10865,12 +10846,12 @@ rec { }; "stackable-shared" = rec { crateName = "stackable-shared"; - version = "0.1.2"; + version = "0.2.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10909,10 +10890,6 @@ rec { packageId = "serde"; features = [ "derive" ]; } - { - name = "serde_yaml"; - packageId = "serde_yaml"; - } { name = "snafu"; packageId = "snafu 0.9.2"; @@ -10927,6 +10904,10 @@ rec { packageId = "time"; optional = true; } + { + name = "yaml_serde"; + packageId = "yaml_serde"; + } ]; devDependencies = [ { @@ -10951,7 +10932,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -11056,12 +11037,12 @@ rec { }; "stackable-versioned" = rec { crateName = "stackable-versioned"; - version = "0.11.1"; + version = "0.13.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11089,10 +11070,6 @@ rec { name = "serde_json"; packageId = "serde_json"; } - { - name = "serde_yaml"; - packageId = "serde_yaml"; - } { name = "snafu"; packageId = "snafu 0.9.2"; @@ -11106,12 +11083,12 @@ rec { }; "stackable-versioned-macros" = rec { crateName = "stackable-versioned-macros"; - version = "0.11.1"; + version = "0.13.0"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11175,7 +11152,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "92e1a3655432e3899da735a9d86ded2e38030c0e"; + rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; @@ -13313,18 +13290,6 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "unsafe-libyaml" = rec { - crateName = "unsafe-libyaml"; - version = "0.2.11"; - edition = "2021"; - crateBin = []; - sha256 = "0qdq69ffl3v5pzx9kzxbghzn0fzn266i1xn70y88maybz9csqfk7"; - libName = "unsafe_libyaml"; - authors = [ - "David Tolnay " - ]; - - }; "untrusted" = rec { crateName = "untrusted"; version = "0.9.0"; @@ -15203,6 +15168,45 @@ rec { ]; }; + "yaml_serde" = rec { + crateName = "yaml_serde"; + version = "0.10.7"; + edition = "2021"; + sha256 = "0679p5sc2zaz7afchb32nradn9jr07w2ngmdpf4ycswsiah2kdrk"; + authors = [ + "YAML Organization " + ]; + dependencies = [ + { + name = "indexmap"; + packageId = "indexmap"; + usesDefaultFeatures = false; + } + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "libyaml-rs"; + packageId = "libyaml-rs"; + } + { + name = "ryu"; + packageId = "ryu"; + } + { + name = "serde"; + packageId = "serde"; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "serde/std" "indexmap/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "yoke" = rec { crateName = "yoke"; version = "0.8.3"; diff --git a/crate-hashes.json b/crate-hashes.json index e4f5f7b1d..a5ee97020 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,11 +1,11 @@ { - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.3": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.119.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.1.2": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.11.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci" } \ No newline at end of file diff --git a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml index 8288ab33a..fb3f2995e 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-agent.yaml @@ -1,6 +1,6 @@ --- # Agent ClusterRole: bound (via per KafkaCluster RoleBinding) to the ServiceAccount that the -# platform-access agent pod runs as. +# agent pod runs as. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml index 96045367c..aafed503c 100644 --- a/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml +++ b/deploy/helm/kafka-operator/templates/clusterrole-operator.yaml @@ -64,7 +64,7 @@ rules: - list - patch - watch - # Deployment of the platform-access agent. + # Deployment of the agent. - apiGroups: - apps resources: diff --git a/extra/crds.yaml b/extra/crds.yaml index 00d43f9b1..d814d144f 100644 --- a/extra/crds.yaml +++ b/extra/crds.yaml @@ -1024,6 +1024,60 @@ spec: nullable: true pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + managementAccess: + description: |- + Management access of the Stackable Data Platform to this Kafka cluster, used to manage + resources like `KafkaTopic`s. The credential must be authorized in Kafka by the user. + nullable: true + properties: + authentication: + description: How the Stackable Data Platform authenticates to Kafka. + properties: + userProvided: + description: A credential provided by the user. + oneOf: + - required: + - anonymous + - required: + - tls + properties: + anonymous: + description: 'No credential: the product does not require authentication.' + type: object + tls: + description: 'Source of a TLS client certificate: a secret-operator SecretClass or a static Secret.' + oneOf: + - required: + - secretClassName + - required: + - secretName + properties: + secretClassName: + description: An AutoTLS SecretClass used to provision the certificate. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + secretName: + description: |- + A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), e.g. as + a Secret of type `kubernetes.io/tls`. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: object + type: object + required: + - userProvided + type: object + enabled: + description: Whether management access is enabled. + type: boolean + required: + - authentication + - enabled + type: object metadataManager: description: |- Metadata manager to use for the Kafka cluster. @@ -2139,52 +2193,6 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array - platformAccess: - description: Access of the Stackable Data Platform to this cluster. - nullable: true - properties: - authentication: - description: How the agent authenticates to Kafka. - oneOf: - - required: - - tls - - required: - - anonymous - properties: - anonymous: - description: 'No credential: the product does not authenticate the agent.' - type: object - tls: - description: 'Source of a TLS client certificate: a secret-operator SecretClass or a static Secret.' - oneOf: - - required: - - secretClass - - required: - - secret - properties: - secret: - description: |- - A static Secret holding the certificate in the keys `tls.crt` and `tls.key` (PEM), e.g. as - a Secret of type `kubernetes.io/tls`. - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - secretClass: - description: An AutoTLS SecretClass used to provision the certificate. - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: object - type: object - enabled: - default: false - description: Whether the operator deploys the agent. False by default. - type: boolean - required: - - authentication - type: object required: - brokers - image diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 4540de068..5986e4ee8 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -346,7 +346,7 @@ impl ValidatedClusterConfig { /// The configuration of the agent deployed with the cluster. pub struct ValidatedAgentConfig { pub image: String, - pub authentication: v1alpha1::KafkaPlatformAccessAuthentication, + pub authentication: v1alpha1::UserProvidedAuthentication, } /// Per-role configuration extracted during validation. @@ -529,16 +529,24 @@ pub fn error_policy( #[cfg(test)] pub(crate) mod test_support { - use std::collections::BTreeMap; + use std::{collections::BTreeMap, str::FromStr}; use stackable_operator::{ + builder::meta::ObjectMetaBuilder, cli::OperatorEnvironmentOptions, commons::networking::DomainName, - crd::listener, + crd::{ + authentication::{core, kerberos, tls}, + listener, + }, utils::{cluster_info::KubernetesClusterInfo, yaml_from_str_singleton_map}, + v2::types::kubernetes::SecretClassName, }; - use super::{ValidatedCluster, dereference::DereferencedObjects, validate::validate}; + use super::{ + ValidatedCluster, dereference::DereferencedObjects, security::ValidatedKafkaSecurity, + validate::validate, + }; use crate::crd::{authentication::ResolvedAuthenticationClasses, v1alpha1}; pub const OPERATOR_IMAGE: &str = "oci.stackable.tech/sdp/kafka-operator:0.0.0-dev"; @@ -559,6 +567,76 @@ pub(crate) mod test_support { yaml_from_str_singleton_map(yaml).expect("invalid test KafkaCluster YAML") } + fn tls_auth_class() -> core::v1alpha1::AuthenticationClass { + core::v1alpha1::AuthenticationClass { + metadata: ObjectMetaBuilder::new().name("tls-auth").build(), + spec: core::v1alpha1::AuthenticationClassSpec { + provider: core::v1alpha1::AuthenticationClassProvider::Tls( + tls::v1alpha1::AuthenticationProvider { + client_cert_secret_class: Some("client-auth-secret-class".to_string()), + }, + ), + }, + } + } + + fn kerberos_auth_class() -> core::v1alpha1::AuthenticationClass { + core::v1alpha1::AuthenticationClass { + metadata: ObjectMetaBuilder::new().name("kerberos-auth").build(), + spec: core::v1alpha1::AuthenticationClassSpec { + provider: core::v1alpha1::AuthenticationClassProvider::Kerberos( + kerberos::v1alpha1::AuthenticationProvider { + kerberos_secret_class: "kerberos-secret-class".to_string(), + }, + ), + }, + } + } + + fn no_auth() -> ResolvedAuthenticationClasses { + ResolvedAuthenticationClasses::new(vec![]) + } + + /// Plaintext: no TLS, no authentication, no OPA. + pub fn plaintext() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + no_auth(), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + None, + None, + ) + } + + /// Server TLS only (encryption without client authentication). + pub fn server_tls() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + no_auth(), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + Some("tls".parse().unwrap()), + None, + ) + } + + /// Mutual TLS (client-certificate authentication). + pub fn client_auth_tls() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + ResolvedAuthenticationClasses::new(vec![tls_auth_class()]), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + Some("tls".parse().unwrap()), + None, + ) + } + + /// Kerberos, which also requires server and internal TLS. + pub fn kerberos() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + ResolvedAuthenticationClasses::new(vec![kerberos_auth_class()]), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + Some("tls".parse().unwrap()), + None, + ) + } + fn cluster_info() -> KubernetesClusterInfo { KubernetesClusterInfo { cluster_domain: DomainName::try_from("cluster.local").expect("valid domain"), diff --git a/rust/operator-binary/src/controller/build/mod.rs b/rust/operator-binary/src/controller/build/mod.rs index 8ddcf577e..e30188571 100644 --- a/rust/operator-binary/src/controller/build/mod.rs +++ b/rust/operator-binary/src/controller/build/mod.rs @@ -390,7 +390,7 @@ mod tests { sorted_names(&resources.role_bindings), ["simple-kafka-rolebinding"] ); - // No agent without platform access. + // No agent without management access. assert!(resources.deployments.is_empty()); } diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index c22ebc625..a903da6fc 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -1,4 +1,4 @@ -//! Builds the resources of the platform-access agent deployed alongside the cluster. +//! Builds the resources of the agent deployed alongside the cluster. use std::str::FromStr; @@ -31,7 +31,7 @@ use crate::{ ValidatedAgentConfig, ValidatedCluster, build::{agent_selector, recommended_labels_for_agent_resources}, }, - crd::v1alpha1::KafkaPlatformAccessAuthentication, + crd::v1alpha1::UserProvidedAuthentication, }; constant!(AGENT_CONTAINER_NAME: ContainerName = "agent"); @@ -45,10 +45,10 @@ pub fn build_agent_deployment( let mut pod_builder = PodBuilder::new(); match &agent_config.authentication { - KafkaPlatformAccessAuthentication::Tls(credential) => { - credential.add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) - } - KafkaPlatformAccessAuthentication::Anonymous(_) => {} + UserProvidedAuthentication::Anonymous(_) => {} + UserProvidedAuthentication::Tls(credential) => credential + .add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) + .expect("the agent Pod has no other volume or mount for the TLS client certificate"), } cb_agent @@ -163,11 +163,14 @@ mod tests { OPERATOR_IMAGE, app_version_label, minimal_kafka, validated_cluster, }; - fn cluster(platform_access: &str) -> ValidatedCluster { - cluster_with_image("{productVersion: 3.9.2}", platform_access) + const TLS_SECRET_CLASS: &str = + "{enabled: true, authentication: {userProvided: {tls: {secretClassName: tls}}}}"; + + fn cluster(management_access: &str) -> ValidatedCluster { + cluster_with_image("{productVersion: 3.9.2}", management_access) } - fn cluster_with_image(image: &str, platform_access: &str) -> ValidatedCluster { + fn cluster_with_image(image: &str, management_access: &str) -> ValidatedCluster { let kafka = minimal_kafka(&format!( r#" apiVersion: kafka.stackable.tech/v1alpha1 @@ -179,8 +182,12 @@ mod tests { spec: image: {image} clusterConfig: - zookeeperConfigMapName: xyz - platformAccess: {platform_access} + metadataManager: kraft + managementAccess: {management_access} + controllers: + roleGroups: + default: + replicas: 1 brokers: roleGroups: default: @@ -194,29 +201,29 @@ mod tests { let agent_config = cluster .agent_config .as_ref() - .expect("platform access is enabled"); + .expect("management access is enabled"); serde_json::to_value(build_agent_deployment(cluster, agent_config)) .expect("must be serializable") } #[test] - fn agent_config_is_only_resolved_if_platform_access_is_enabled() { + fn agent_config_is_only_resolved_if_management_access_is_enabled() { assert!( - cluster("{enabled: false, authentication: {tls: {secretClass: tls}}}") - .agent_config - .is_none() + cluster( + "{enabled: false, authentication: {userProvided: {tls: {secretClassName: tls}}}}" + ) + .agent_config + .is_none() ); - let cluster = cluster("{enabled: true, authentication: {tls: {secretClass: tls}}}"); - let agent_config = cluster.agent_config.expect("platform access is enabled"); + let cluster = cluster(TLS_SECRET_CLASS); + let agent_config = cluster.agent_config.expect("management access is enabled"); assert_eq!(agent_config.image, OPERATOR_IMAGE); } #[test] fn test_deployment() { - let deployment = agent_deployment(&cluster( - "{enabled: true, authentication: {tls: {secretClass: tls}}}", - )); + let deployment = agent_deployment(&cluster(TLS_SECRET_CLASS)); assert_eq!(deployment["metadata"]["name"], "simple-kafka-agent"); assert_eq!(deployment["spec"]["replicas"], 1); @@ -230,7 +237,7 @@ mod tests { assert_eq!( deployment["spec"]["selector"]["matchLabels"], json!({ - "app.kubernetes.io/component": "agent", + "app.kubernetes.io/component": "kafka-agent", "app.kubernetes.io/instance": "simple-kafka", "app.kubernetes.io/name": "kafka" }) @@ -238,7 +245,7 @@ mod tests { assert_eq!( deployment["spec"]["template"]["metadata"]["labels"], json!({ - "app.kubernetes.io/component": "agent", + "app.kubernetes.io/component": "kafka-agent", "app.kubernetes.io/instance": "simple-kafka", "app.kubernetes.io/managed-by": "kafka.stackable.tech_kafkacluster", "app.kubernetes.io/name": "kafka", @@ -257,9 +264,9 @@ mod tests { assert_eq!(pod_spec["containers"][0]["args"], json!(["run"])); assert_eq!( pod_spec["containers"][0]["volumeMounts"], - json!([{"mountPath": "/stackable/secrets/tls-platform-access", "name": "tls-platform-access"}]) + json!([{"mountPath": "/stackable/secrets/tls-management-access", "name": "tls-management-access"}]) ); - assert_eq!(pod_spec["volumes"][0]["name"], "tls-platform-access"); + assert_eq!(pod_spec["volumes"][0]["name"], "tls-management-access"); assert_eq!( pod_spec["volumes"][0]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"]["secrets.stackable.tech/class"], "tls" @@ -269,19 +276,20 @@ mod tests { #[test] fn test_deployment_with_static_secret() { let deployment = agent_deployment(&cluster( - "{enabled: true, authentication: {tls: {secret: my-cert}}}", + "{enabled: true, authentication: {userProvided: {tls: {secretName: my-cert}}}}", )); assert_eq!( deployment["spec"]["template"]["spec"]["volumes"], - json!([{"name": "tls-platform-access", "secret": {"secretName": "my-cert"}}]) + json!([{"name": "tls-management-access", "secret": {"optional": false, "secretName": "my-cert"}}]) ); } #[test] fn deployment_with_anonymous_authentication_mounts_no_credential() { - let deployment = - agent_deployment(&cluster("{enabled: true, authentication: {anonymous: {}}}")); + let deployment = agent_deployment(&cluster( + "{enabled: true, authentication: {userProvided: {anonymous: {}}}}", + )); let pod_spec = &deployment["spec"]["template"]["spec"]; assert_eq!(pod_spec["volumes"], Value::Null); @@ -292,7 +300,7 @@ mod tests { fn test_deployment_uses_product_image_pull_secrets() { let deployment = agent_deployment(&cluster_with_image( "{productVersion: 3.9.2, pullSecrets: [{name: regcred}]}", - "{enabled: true, authentication: {tls: {secretClass: tls}}}", + TLS_SECRET_CLASS, )); assert_eq!( @@ -303,7 +311,7 @@ mod tests { #[test] fn test_role_binding() { - let cluster = cluster("{enabled: true, authentication: {tls: {secretClass: tls}}}"); + let cluster = cluster(TLS_SECRET_CLASS); assert_eq!( json!({ @@ -311,7 +319,7 @@ mod tests { "kind": "RoleBinding", "metadata": { "labels": { - "app.kubernetes.io/component": "agent", + "app.kubernetes.io/component": "kafka-agent", "app.kubernetes.io/instance": "simple-kafka", "app.kubernetes.io/managed-by": "kafka.stackable.tech_kafkacluster", "app.kubernetes.io/name": "kafka", diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index 2a2dabd26..1280baf0b 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -6,7 +6,7 @@ use std::{collections::BTreeMap, str::FromStr}; use serde::Serialize; -use snafu::{OptionExt, ResultExt, Snafu}; +use snafu::{OptionExt, ResultExt, Snafu, ensure}; use stackable_operator::{ cli::OperatorEnvironmentOptions, commons::product_image_selection, @@ -117,10 +117,24 @@ pub enum Error { MissingKraftControllerRole, #[snafu(display( - "platform access requires the operator image, which also contains the agent; set the \ + "management access requires the operator image, which also contains the agent; set the \ OPERATOR_IMAGE environment variable of the operator" ))] - PlatformAccessRequiresOperatorImage, + ManagementAccessRequiresOperatorImage, + + #[snafu(display("management access is only supported in KRaft mode"))] + ManagementAccessRequiresKraft, + + #[snafu(display("management access does not support clusters with Kerberos authentication"))] + ManagementAccessWithKerberos, + + #[snafu(display( + "the cluster requires client authentication, but management access is anonymous" + ))] + AnonymousManagementAccessWithClientAuthentication, + + #[snafu(display("TLS management access requires the cluster to use TLS"))] + TlsManagementAccessRequiresTls, } /// Validated logging configuration for a Kafka role group's Kafka and (optional) Vector @@ -346,15 +360,24 @@ pub fn validate( let agent_config = kafka .spec - .platform_access + .cluster_config + .management_access .as_ref() - .filter(|platform_access| platform_access.enabled) - .map(|platform_access| { + .filter(|management_access| management_access.enabled) + .map(|management_access| { + ensure!( + metadata_manager == crate::crd::MetadataManager::KRaft, + ManagementAccessRequiresKraftSnafu + ); + validate_management_access( + &management_access.authentication.user_provided, + &kafka_security, + )?; Ok(ValidatedAgentConfig { image: operator_image - .context(PlatformAccessRequiresOperatorImageSnafu)? + .context(ManagementAccessRequiresOperatorImageSnafu)? .to_owned(), - authentication: platform_access.authentication.clone(), + authentication: management_access.authentication.user_provided.clone(), }) }) .transpose()?; @@ -467,22 +490,106 @@ fn inject_cluster_id(env_overrides: EnvVarSet, cluster_id: Option<&str>) -> EnvV } } +/// Rejects management access authentication config that cannot connect to the cluster. +fn validate_management_access( + authentication: &v1alpha1::UserProvidedAuthentication, + security: &ValidatedKafkaSecurity, +) -> Result<()> { + ensure!( + !security.has_kerberos_enabled(), + ManagementAccessWithKerberosSnafu + ); + + match authentication { + v1alpha1::UserProvidedAuthentication::Anonymous(_) => ensure!( + security.tls_client_authentication_class().is_none(), + AnonymousManagementAccessWithClientAuthenticationSnafu + ), + v1alpha1::UserProvidedAuthentication::Tls(_) => { + ensure!(security.tls_enabled(), TlsManagementAccessRequiresTlsSnafu) + } + } + + Ok(()) +} + #[cfg(test)] mod tests { use std::str::FromStr; - use stackable_operator::v2::{ - builder::pod::container::EnvVarSet, types::operator::RoleGroupName, + use rstest::rstest; + use stackable_operator::{ + crd::management_access::v1alpha1::{Anonymous, TlsClientCredential}, + v2::{ + builder::pod::container::EnvVarSet, + types::{kubernetes::SecretName, operator::RoleGroupName}, + }, }; - use super::{Error, KAFKA_CLUSTER_ID, inject_cluster_id}; + use super::{Error, KAFKA_CLUSTER_ID, inject_cluster_id, validate_management_access}; use crate::{ - controller::test_support::{ - app_version_label, minimal_kafka, validate_with_operator_image, validated_cluster, + controller::{ + security::ValidatedKafkaSecurity, + test_support::{ + app_version_label, client_auth_tls, kerberos, minimal_kafka, plaintext, server_tls, + validate_with_operator_image, validated_cluster, + }, }, - crd::role::KafkaRole, + crd::{role::KafkaRole, v1alpha1::UserProvidedAuthentication}, }; + fn anonymous() -> UserProvidedAuthentication { + UserProvidedAuthentication::Anonymous(Anonymous::default()) + } + + fn tls() -> UserProvidedAuthentication { + UserProvidedAuthentication::Tls(TlsClientCredential::SecretName( + SecretName::from_str("agent-cert").expect("the Secret name should be valid"), + )) + } + + #[rstest] + #[case::plaintext_anonymous(plaintext(), anonymous())] + #[case::server_tls_anonymous(server_tls(), anonymous())] + #[case::server_tls_with_credential(server_tls(), tls())] + #[case::client_auth_with_credential(client_auth_tls(), tls())] + fn accept_management_access( + #[case] security: ValidatedKafkaSecurity, + #[case] authentication: UserProvidedAuthentication, + ) { + validate_management_access(&authentication, &security) + .expect("the management access should be valid"); + } + + #[rstest] + #[case::anonymous(anonymous())] + #[case::tls(tls())] + fn reject_management_access_with_kerberos(#[case] authentication: UserProvidedAuthentication) { + let error = validate_management_access(&authentication, &kerberos()) + .expect_err("the management access should be invalid"); + + assert!(matches!(error, Error::ManagementAccessWithKerberos)); + } + + #[test] + fn reject_anonymous_management_access_with_client_authentication() { + let error = validate_management_access(&anonymous(), &client_auth_tls()) + .expect_err("the management access should be invalid"); + + assert!(matches!( + error, + Error::AnonymousManagementAccessWithClientAuthentication + )); + } + + #[test] + fn reject_tls_management_access_without_tls() { + let error = validate_management_access(&tls(), &plaintext()) + .expect_err("the management access should be invalid"); + + assert!(matches!(error, Error::TlsManagementAccessRequiresTls)); + } + #[test] fn test_constants() { // Test that dereferencing the constants does not panic. @@ -584,7 +691,7 @@ mod tests { #[rstest::rstest] #[case::enabled(true)] #[case::disabled(false)] - fn platform_access_requires_the_operator_image(#[case] enabled: bool) { + fn management_access_requires_the_operator_image(#[case] enabled: bool) { let kafka = minimal_kafka(&format!( r#" apiVersion: kafka.stackable.tech/v1alpha1 @@ -597,12 +704,17 @@ mod tests { image: productVersion: 3.9.2 clusterConfig: - zookeeperConfigMapName: xyz - platformAccess: - enabled: {enabled} - authentication: - tls: - secretClass: tls + metadataManager: kraft + managementAccess: + enabled: {enabled} + authentication: + userProvided: + tls: + secretClassName: tls + controllers: + roleGroups: + default: + replicas: 1 brokers: roleGroups: default: @@ -614,8 +726,8 @@ mod tests { if enabled { assert!( - matches!(result, Err(Error::PlatformAccessRequiresOperatorImage)), - "expected PlatformAccessRequiresOperatorImage, got: {:?}", + matches!(result, Err(Error::ManagementAccessRequiresOperatorImage)), + "expected ManagementAccessRequiresOperatorImage, got: {:?}", result.err() ); } else { @@ -623,6 +735,42 @@ mod tests { } } + #[test] + fn zookeeper_mode_rejects_management_access() { + let kafka = minimal_kafka( + r#" + apiVersion: kafka.stackable.tech/v1alpha1 + kind: KafkaCluster + metadata: + name: simple-kafka + namespace: default + uid: 12345678-1234-1234-1234-123456789012 + spec: + image: + productVersion: 3.9.2 + clusterConfig: + zookeeperConfigMapName: zk-discovery + managementAccess: + enabled: true + authentication: + userProvided: + anonymous: {} + brokers: + roleGroups: + default: + replicas: 3 + "#, + ); + + let result = crate::controller::test_support::validate_err(&kafka); + + assert!( + matches!(result, Err(Error::ManagementAccessRequiresKraft)), + "expected ManagementAccessRequiresKraft, got: {:?}", + result.err() + ); + } + #[test] fn injects_cluster_id_when_absent() { let env = inject_cluster_id(EnvVarSet::new(), Some("my-id")); diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 7b43745f5..3faba948e 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -18,7 +18,7 @@ use stackable_operator::{ }, config::merge::Merge, constant, - crd::platform_access::v1alpha1::{Anonymous, TlsClientCredential}, + crd::management_access::v1alpha1::{Anonymous, TlsClientCredential}, deep_merger::ObjectOverrides, kube::{CustomResource, runtime::reflector::ObjectRef}, role_utils::GenericRoleConfig, @@ -150,10 +150,6 @@ pub mod versioned { #[serde(default)] pub cluster_config: v1alpha1::KafkaClusterConfig, - /// Access of the Stackable Data Platform to this cluster. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub platform_access: Option, - // no doc - docs in ClusterOperation struct. #[serde(default)] pub cluster_operation: ClusterOperation, @@ -163,27 +159,6 @@ pub mod versioned { pub object_overrides: ObjectOverrides, } - /// Access of the Stackable Data Platform to this Kafka cluster, used by an agent to manage - /// resources like `KafkaTopic`s. The credential must be authorized in Kafka by the user. - #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - pub struct KafkaPlatformAccess { - /// Whether the operator deploys the agent. False by default. - #[serde(default)] - pub enabled: bool, - - /// How the agent authenticates to Kafka. - pub authentication: v1alpha1::KafkaPlatformAccessAuthentication, - } - - /// How the agent authenticates to Kafka. - #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] - #[serde(rename_all = "camelCase")] - pub enum KafkaPlatformAccessAuthentication { - Tls(TlsClientCredential), - Anonymous(Anonymous), - } - #[derive(Clone, Deserialize, Debug, Eq, JsonSchema, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct KafkaClusterConfig { @@ -267,6 +242,37 @@ pub mod versioned { /// #[serde(skip_serializing_if = "Option::is_none")] pub broker_id_pod_config_map_name: Option, + + // no doc - docs in KafkaManagementAccess struct. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub management_access: Option, + } + + /// Management access of the Stackable Data Platform to this Kafka cluster, used to manage + /// resources like `KafkaTopic`s. The credential must be authorized in Kafka by the user. + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct KafkaManagementAccess { + /// Whether management access is enabled. + pub enabled: bool, + + /// How the Stackable Data Platform authenticates to Kafka. + pub authentication: v1alpha1::KafkaManagementAccessAuthentication, + } + + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct KafkaManagementAccessAuthentication { + // no doc - docs in UserProvidedAuthentication enum. + pub user_provided: v1alpha1::UserProvidedAuthentication, + } + + /// A credential provided by the user. + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub enum UserProvidedAuthentication { + Anonymous(Anonymous), + Tls(TlsClientCredential), } #[derive(Clone, Debug, Default, Deserialize, JsonSchema, Merge, PartialEq, Serialize)] @@ -300,6 +306,7 @@ impl Default for v1alpha1::KafkaClusterConfig { zookeeper_config_map_name: None, metadata_manager: None, broker_id_pod_config_map_name: None, + management_access: None, } } } diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 817b07ac1..8ef5b8398 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -186,9 +186,10 @@ async fn main() -> anyhow::Result<()> { ) .owns( watch_namespace.get_api::>(&client), - // The agent is a the only Deployment - watcher::Config::default() - .labels("app.kubernetes.io/name=kafka,app.kubernetes.io/component=agent"), + // The agent is the only Deployment + watcher::Config::default().labels( + "app.kubernetes.io/name=kafka,app.kubernetes.io/component=kafka-agent", + ), ) .watches( watch_namespace.get_api::>(&client), From 1d684766e91abf28f9695e07e5c44f9c3803cc2f Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Fri, 23 Oct 2026 20:52:16 +0200 Subject: [PATCH 15/25] configure the agent's connection to Kafka via a shared contract crate --- Cargo.lock | 10 + Cargo.nix | 43 ++++ Cargo.toml | 3 +- rust/operator-binary/Cargo.toml | 1 + rust/operator-binary/src/controller.rs | 49 ++++- .../src/controller/build/command.rs | 2 +- .../src/controller/build/resource/agent.rs | 196 ++++++++++++++---- .../controller/build/resource/statefulset.rs | 2 +- .../src/controller/build/security.rs | 120 +---------- .../src/controller/security.rs | 12 ++ .../src/controller/validate.rs | 129 +++++++++--- rust/shared/Cargo.toml | 17 ++ rust/shared/src/agent.rs | 42 ++++ rust/shared/src/lib.rs | 1 + 14 files changed, 434 insertions(+), 193 deletions(-) create mode 100644 rust/shared/Cargo.toml create mode 100644 rust/shared/src/agent.rs create mode 100644 rust/shared/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 42c5394f6..f092e03d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3216,12 +3216,22 @@ dependencies = [ "serde", "serde_json", "snafu 0.9.2", + "stackable-kafka-shared", "stackable-operator", "strum", "tokio", "tracing", ] +[[package]] +name = "stackable-kafka-shared" +version = "0.0.0-dev" +dependencies = [ + "rstest", + "stackable-operator", + "strum", +] + [[package]] name = "stackable-operator" version = "0.121.0" diff --git a/Cargo.nix b/Cargo.nix index 7b49d7c1a..e3bd3c098 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -59,6 +59,16 @@ rec { packageId = "stackable-kafka-operator"; }; + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + "stackable-kafka-shared" = rec { + packageId = "stackable-kafka-shared"; + build = internal.buildRustCrateWithFeatures { + packageId = "stackable-kafka-shared"; + }; + # Debug support which might change between releases. # File a bug if you depend on any for non-debug work! debug = internal.debugCrate { inherit packageId; }; @@ -10575,6 +10585,10 @@ rec { name = "snafu"; packageId = "snafu 0.9.2"; } + { + name = "stackable-kafka-shared"; + packageId = "stackable-kafka-shared"; + } { name = "stackable-operator"; packageId = "stackable-operator"; @@ -10609,6 +10623,35 @@ rec { } ]; + }; + "stackable-kafka-shared" = rec { + crateName = "stackable-kafka-shared"; + version = "0.0.0-dev"; + edition = "2024"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./rust/shared; }; + libName = "stackable_kafka_shared"; + authors = [ + "Stackable GmbH " + ]; + dependencies = [ + { + name = "stackable-operator"; + packageId = "stackable-operator"; + features = [ "crds" "webhook" ]; + } + { + name = "strum"; + packageId = "strum"; + features = [ "derive" ]; + } + ]; + devDependencies = [ + { + name = "rstest"; + packageId = "rstest"; + } + ]; + }; "stackable-operator" = rec { crateName = "stackable-operator"; diff --git a/Cargo.toml b/Cargo.toml index 975fdca36..81beda9ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["rust/operator-binary", "rust/agent-binary"] +members = ["rust/operator-binary", "rust/agent-binary", "rust/shared"] resolver = "2" [workspace.package] @@ -11,6 +11,7 @@ repository = "https://github.com/stackabletech/kafka-operator" [workspace.dependencies] stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", branch = "feat/platform-access", features = ["crds", "webhook"] } +stackable-kafka-shared = { path = "rust/shared" } anyhow = "1.0" built = { version = "0.8", features = ["chrono", "git2"] } diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 38e9e1e18..ca41d66db 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -9,6 +9,7 @@ repository.workspace = true publish = false [dependencies] +stackable-kafka-shared.workspace = true stackable-operator.workspace = true indoc.workspace = true diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 5986e4ee8..368bbdf2b 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -15,12 +15,13 @@ use std::{ use const_format::concatcp; use snafu::{ResultExt, Snafu}; +use stackable_kafka_shared::agent::ClientSecurity; use stackable_operator::{ cli::OperatorEnvironmentOptions, cluster_resources::ClusterResourceApplyStrategy, commons::{networking::DomainName, product_image_selection::ResolvedProductImage}, constant, - crd::listener, + crd::{listener, management_access::v1alpha1::TlsClientCredential}, k8s_openapi::api::{ apps::v1::{Deployment, StatefulSet}, core::v1::{ConfigMap, Service, ServiceAccount}, @@ -40,7 +41,7 @@ use stackable_operator::{ role_group_utils::ResourceNames, role_utils, types::{ - kubernetes::{ConfigMapName, ListenerName, NamespaceName, Uid}, + kubernetes::{ConfigMapName, ListenerName, NamespaceName, SecretClassName, Uid}, operator::{ClusterName, ControllerName, OperatorName, ProductName, ProductVersion}, }, }, @@ -346,7 +347,29 @@ impl ValidatedClusterConfig { /// The configuration of the agent deployed with the cluster. pub struct ValidatedAgentConfig { pub image: String, - pub authentication: v1alpha1::UserProvidedAuthentication, + pub connection: AgentConnection, +} + +#[derive(Debug, PartialEq)] +pub enum AgentConnection { + Plaintext, + Tls { + server_ca_secret_class: SecretClassName, + }, + MutualTls { + server_ca_secret_class: SecretClassName, + client_credential: TlsClientCredential, + }, +} + +impl From<&AgentConnection> for ClientSecurity { + fn from(connection: &AgentConnection) -> Self { + match connection { + AgentConnection::Plaintext => Self::Plaintext, + AgentConnection::Tls { .. } => Self::Tls, + AgentConnection::MutualTls { .. } => Self::MutualTls, + } + } } /// Per-role configuration extracted during validation. @@ -637,6 +660,26 @@ pub(crate) mod test_support { ) } + /// Internal TLS only (broker/controller encryption without client TLS). + pub fn internal_tls() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + no_auth(), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + None, + None, + ) + } + + /// OPA authorization with a TLS truststore (internal + server TLS also enabled). + pub fn opa() -> ValidatedKafkaSecurity { + ValidatedKafkaSecurity::new( + no_auth(), + SecretClassName::from_str("tls").expect("tls secret class name is valid"), + Some("tls".parse().unwrap()), + Some("opa-tls".parse().unwrap()), + ) + } + fn cluster_info() -> KubernetesClusterInfo { KubernetesClusterInfo { cluster_domain: DomainName::try_from("cluster.local").expect("valid domain"), diff --git a/rust/operator-binary/src/controller/build/command.rs b/rust/operator-binary/src/controller/build/command.rs index ebe59764d..34ff1e6ad 100644 --- a/rust/operator-binary/src/controller/build/command.rs +++ b/rust/operator-binary/src/controller/build/command.rs @@ -400,7 +400,7 @@ mod tests { use indoc::indoc; use super::*; - use crate::controller::build::security::tests::{kerberos, plaintext}; + use crate::controller::test_support::{kerberos, plaintext}; #[test] fn controller_command_does_not_export_a_realm_without_kerberos() { diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index a903da6fc..19fcd4332 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -2,39 +2,52 @@ use std::str::FromStr; +use stackable_kafka_shared::agent::{ + ClientSecurity, DISCOVERY_DIR, ENV_CLIENT_SECURITY, ENV_CLUSTER_NAME, ENV_CLUSTER_NAMESPACE, + KAFKA_TLS_DIR, +}; use stackable_operator::{ builder::{ meta::ObjectMetaBuilder, pod::{ - PodBuilder, resources::ResourceRequirementsBuilder, security::PodSecurityContextBuilder, + PodBuilder, + container::ContainerBuilder, + resources::ResourceRequirementsBuilder, + security::PodSecurityContextBuilder, + volume::{SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder}, }, }, + commons::secret_class::SecretClassVolumeProvisionParts, constant, k8s_openapi::{ Resource, api::{ apps::v1::{Deployment, DeploymentSpec, DeploymentStrategy}, - core::v1::{EnvVarSource, ObjectFieldSelector, ServiceAccount}, + core::v1::{EnvVar, EnvVarSource, ObjectFieldSelector, ServiceAccount}, rbac::v1::{ClusterRole, RoleBinding, RoleRef, Subject}, }, apimachinery::pkg::apis::meta::v1::LabelSelector, }, kube::api::ObjectMeta, v2::{ - builder::{meta::ownerreference_from_resource, pod::container::new_container_builder}, - types::kubernetes::ContainerName, + builder::{ + meta::ownerreference_from_resource, + pod::container::{EnvVarName, EnvVarSet, new_container_builder}, + }, + types::kubernetes::{ContainerName, SecretClassName, VolumeName}, }, }; -use crate::{ - controller::{ - ValidatedAgentConfig, ValidatedCluster, - build::{agent_selector, recommended_labels_for_agent_resources}, - }, - crd::v1alpha1::UserProvidedAuthentication, +use crate::controller::{ + AgentConnection, ValidatedAgentConfig, ValidatedCluster, + build::{agent_selector, recommended_labels_for_agent_resources}, }; constant!(AGENT_CONTAINER_NAME: ContainerName = "agent"); +constant!(DISCOVERY_VOLUME_NAME: VolumeName = "discovery"); +constant!(KAFKA_TLS_VOLUME_NAME: VolumeName = "tls-kafka"); +constant!(KUBERNETES_NODE_NAME: EnvVarName = "KUBERNETES_NODE_NAME"); +constant!(KUBERNETES_CLUSTER_DOMAIN: EnvVarName = "KUBERNETES_CLUSTER_DOMAIN"); pub const AGENT_CLUSTER_ROLE_NAME: &str = "kafka-agent-clusterrole"; pub fn build_agent_deployment( @@ -44,32 +57,32 @@ pub fn build_agent_deployment( let mut cb_agent = new_container_builder(&AGENT_CONTAINER_NAME); let mut pod_builder = PodBuilder::new(); - match &agent_config.authentication { - UserProvidedAuthentication::Anonymous(_) => {} - UserProvidedAuthentication::Tls(credential) => credential - .add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) - .expect("the agent Pod has no other volume or mount for the TLS client certificate"), + add_discovery_volume_and_mount(cluster, &mut pod_builder, &mut cb_agent); + match &agent_config.connection { + AgentConnection::Plaintext => {} + AgentConnection::Tls { + server_ca_secret_class, + } => { + add_kafka_tls_volume_and_mount(server_ca_secret_class, &mut pod_builder, &mut cb_agent) + } + AgentConnection::MutualTls { + server_ca_secret_class, + client_credential, + } => { + add_kafka_tls_volume_and_mount(server_ca_secret_class, &mut pod_builder, &mut cb_agent); + client_credential + .add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) + .expect( + "the agent Pod has no other volume or mount for the TLS client certificate", + ); + } } cb_agent .image(&agent_config.image) .command(vec!["stackable-kafka-agent".to_owned()]) .args(vec!["run".to_owned()]) - .add_env_var_from_source( - "KUBERNETES_NODE_NAME", - EnvVarSource { - field_ref: Some(ObjectFieldSelector { - field_path: "spec.nodeName".to_owned(), - ..ObjectFieldSelector::default() - }), - ..EnvVarSource::default() - }, - ) - // Saves the agent from looking the domain up via the kubelet, which needs extra RBAC. - .add_env_var( - "KUBERNETES_CLUSTER_DOMAIN", - cluster.cluster_domain.to_string(), - ) + .add_env_vars(agent_env_vars(cluster, agent_config)) .resources( ResourceRequirementsBuilder::new() .with_cpu_request("100m") @@ -139,6 +152,80 @@ pub fn build_agent_role_binding(cluster: &ValidatedCluster) -> RoleBinding { } } +fn agent_env_vars(cluster: &ValidatedCluster, agent_config: &ValidatedAgentConfig) -> EnvVarSet { + let node_name_env_var = EnvVar { + name: KUBERNETES_NODE_NAME.to_string(), + value: None, + value_from: Some(EnvVarSource { + field_ref: Some(ObjectFieldSelector { + field_path: "spec.nodeName".to_owned(), + ..ObjectFieldSelector::default() + }), + ..EnvVarSource::default() + }), + }; + + EnvVarSet::new() + .with_value(&ENV_CLUSTER_NAME, cluster.name.to_string()) + .with_value(&ENV_CLUSTER_NAMESPACE, cluster.namespace.to_string()) + .with_value( + &ENV_CLIENT_SECURITY, + ClientSecurity::from(&agent_config.connection).to_string(), + ) + // Saves the agent from looking the domain up via the kubelet, which needs extra RBAC. + .with_value( + &KUBERNETES_CLUSTER_DOMAIN, + cluster.cluster_domain.to_string(), + ) + .with_env_var(node_name_env_var) + .expect("the env var name is a valid EnvVarName") +} + +fn add_discovery_volume_and_mount( + cluster: &ValidatedCluster, + pod_builder: &mut PodBuilder, + container_builder: &mut ContainerBuilder, +) { + pod_builder + .add_volume( + VolumeBuilder::new(&*DISCOVERY_VOLUME_NAME) + .with_config_map(cluster.name.to_string()) + .build(), + ) + .expect("the volume name is statically defined and must not collide"); + container_builder + .add_volume_mount(&*DISCOVERY_VOLUME_NAME, DISCOVERY_DIR) + .expect("the mount path is statically defined and must not collide"); +} + +fn add_kafka_tls_volume_and_mount( + secret_class: &SecretClassName, + pod_builder: &mut PodBuilder, + container_builder: &mut ContainerBuilder, +) { + pod_builder + .add_volume( + VolumeBuilder::new(&*KAFKA_TLS_VOLUME_NAME) + .ephemeral( + SecretOperatorVolumeSourceBuilder::new( + secret_class, + SecretClassVolumeProvisionParts::Public, + ) + .with_format(SecretFormat::TlsPem) + .build() + .expect( + "the annotations are built from a valid SecretClass name and constant \ + values", + ), + ) + .build(), + ) + .expect("the volume name is statically defined and must not collide"); + container_builder + .add_volume_mount(&*KAFKA_TLS_VOLUME_NAME, KAFKA_TLS_DIR) + .expect("the mount path is statically defined and must not collide"); +} + /// The name of all agent resources. Kinds don't share a namespace, so unlike a suffix per kind, this /// cannot collide with the resources of a cluster named `-agent`. fn agent_name(cluster: &ValidatedCluster) -> String { @@ -264,12 +351,38 @@ mod tests { assert_eq!(pod_spec["containers"][0]["args"], json!(["run"])); assert_eq!( pod_spec["containers"][0]["volumeMounts"], - json!([{"mountPath": "/stackable/secrets/tls-management-access", "name": "tls-management-access"}]) + json!([ + {"mountPath": "/stackable/discovery", "name": "discovery"}, + {"mountPath": "/stackable/secrets/tls-kafka", "name": "tls-kafka"}, + {"mountPath": "/stackable/secrets/tls-management-access", "name": "tls-management-access"} + ]) ); - assert_eq!(pod_spec["volumes"][0]["name"], "tls-management-access"); assert_eq!( - pod_spec["volumes"][0]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"]["secrets.stackable.tech/class"], - "tls" + pod_spec["volumes"][0]["configMap"], + json!({"name": "simple-kafka"}) + ); + assert_eq!( + pod_spec["volumes"][1]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"], + json!({ + "secrets.stackable.tech/class": "tls", + "secrets.stackable.tech/format": "tls-pem", + "secrets.stackable.tech/provision-parts": "public" + }) + ); + assert_eq!(pod_spec["volumes"][2]["name"], "tls-management-access"); + + assert_eq!( + pod_spec["containers"][0]["env"], + json!([ + {"name": "KAFKA_CLIENT_SECURITY", "value": "mutual-tls"}, + {"name": "KAFKA_CLUSTER_NAME", "value": "simple-kafka"}, + {"name": "KAFKA_CLUSTER_NAMESPACE", "value": "default"}, + {"name": "KUBERNETES_CLUSTER_DOMAIN", "value": "cluster.local"}, + { + "name": "KUBERNETES_NODE_NAME", + "valueFrom": {"fieldRef": {"fieldPath": "spec.nodeName"}} + } + ]) ); } @@ -280,20 +393,25 @@ mod tests { )); assert_eq!( - deployment["spec"]["template"]["spec"]["volumes"], - json!([{"name": "tls-management-access", "secret": {"optional": false, "secretName": "my-cert"}}]) + deployment["spec"]["template"]["spec"]["volumes"][2], + json!({"name": "tls-management-access", "secret": {"optional": false, "secretName": "my-cert"}}) ); } #[test] - fn deployment_with_anonymous_authentication_mounts_no_credential() { + fn deployment_with_anonymous_authentication_verifies_brokers_without_credential() { let deployment = agent_deployment(&cluster( "{enabled: true, authentication: {userProvided: {anonymous: {}}}}", )); let pod_spec = &deployment["spec"]["template"]["spec"]; - assert_eq!(pod_spec["volumes"], Value::Null); - assert_eq!(pod_spec["containers"][0]["volumeMounts"], Value::Null); + assert_eq!(pod_spec["volumes"][0]["name"], "discovery"); + assert_eq!(pod_spec["volumes"][1]["name"], "tls-kafka"); + assert_eq!(pod_spec["volumes"][2], Value::Null); + assert_eq!( + pod_spec["containers"][0]["env"][0], + json!({"name": "KAFKA_CLIENT_SECURITY", "value": "tls"}) + ); } #[test] diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index 4ea3b886f..ed56b0928 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -982,7 +982,7 @@ mod tests { #[test] fn quorum_manager_container_env_can_be_overridden() { let resolved_product_image = test_resolved_product_image(); - let kafka_security = crate::controller::build::security::tests::kerberos(); + let kafka_security = crate::controller::test_support::kerberos(); assert!( kafka_security.has_kerberos_enabled(), "sanity check failed: the fixture must have Kerberos enabled so that KRB5_CONFIG \ diff --git a/rust/operator-binary/src/controller/build/security.rs b/rust/operator-binary/src/controller/build/security.rs index 0906bf7ef..74dbc0149 100644 --- a/rust/operator-binary/src/controller/build/security.rs +++ b/rust/operator-binary/src/controller/build/security.rs @@ -17,7 +17,6 @@ use stackable_operator::{ }, commons::secret_class::SecretClassVolumeProvisionParts, constant, - crd::authentication::core, k8s_openapi::api::core::v1::Volume, shared::time::Duration, v2::types::kubernetes::VolumeName, @@ -277,7 +276,7 @@ pub fn add_broker_volume_and_volume_mounts( requested_secret_lifetime: &Duration, ) -> Result<(), Error> { // add tls (server or client authentication volumes) if required - if let Some(tls_server_secret_class) = tls_secret_class(security) { + if let Some(tls_server_secret_class) = security.tls_secret_class() { // We have to mount tls pem files for kcat's readiness-probe command (the mount can be // used directly) pod_builder @@ -607,19 +606,6 @@ pub fn controller_config_settings(security: &ValidatedKafkaSecurity) -> BTreeMap config } -/// Returns the `SecretClass` provided in a `AuthenticationClass` for TLS. -fn tls_secret_class(security: &ValidatedKafkaSecurity) -> Option<&str> { - security - .tls_client_authentication_class() - .and_then(|auth_class| match &auth_class.spec.provider { - core::v1alpha1::AuthenticationClassProvider::Tls(tls) => { - tls.client_cert_secret_class.as_deref() - } - _ => None, - }) - .or_else(|| security.tls_server_secret_class()) -} - /// Creates ephemeral volumes to mount the `SecretClass` into the Pods for kcat client fn create_kcat_tls_volume( volume_name: &VolumeName, @@ -711,107 +697,13 @@ fn kcat_client_sasl_ssl(cert_directory: &str, service_name: &str) -> Vec } #[cfg(test)] -pub(crate) mod tests { - use std::{collections::BTreeMap, str::FromStr}; - - use stackable_operator::{ - builder::meta::ObjectMetaBuilder, - crd::authentication::{core, kerberos, tls}, - v2::types::kubernetes::SecretClassName, - }; +mod tests { + use std::collections::BTreeMap; use super::*; - use crate::crd::authentication::ResolvedAuthenticationClasses; - - fn tls_auth_class() -> core::v1alpha1::AuthenticationClass { - core::v1alpha1::AuthenticationClass { - metadata: ObjectMetaBuilder::new().name("tls-auth").build(), - spec: core::v1alpha1::AuthenticationClassSpec { - provider: core::v1alpha1::AuthenticationClassProvider::Tls( - tls::v1alpha1::AuthenticationProvider { - client_cert_secret_class: Some("client-auth-secret-class".to_string()), - }, - ), - }, - } - } - - fn kerberos_auth_class() -> core::v1alpha1::AuthenticationClass { - core::v1alpha1::AuthenticationClass { - metadata: ObjectMetaBuilder::new().name("kerberos-auth").build(), - spec: core::v1alpha1::AuthenticationClassSpec { - provider: core::v1alpha1::AuthenticationClassProvider::Kerberos( - kerberos::v1alpha1::AuthenticationProvider { - kerberos_secret_class: "kerberos-secret-class".to_string(), - }, - ), - }, - } - } - - fn no_auth() -> ResolvedAuthenticationClasses { - ResolvedAuthenticationClasses::new(vec![]) - } - - /// Plaintext: no TLS, no authentication, no OPA. - pub(crate) fn plaintext() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - no_auth(), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - None, - None, - ) - } - - /// Server TLS only (encryption without client authentication). - fn server_tls() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - no_auth(), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - Some("tls".parse().unwrap()), - None, - ) - } - - /// Mutual TLS (client-certificate authentication). - fn client_auth_tls() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - ResolvedAuthenticationClasses::new(vec![tls_auth_class()]), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - Some("tls".parse().unwrap()), - None, - ) - } - - /// Kerberos, which also requires server and internal TLS. - pub(crate) fn kerberos() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - ResolvedAuthenticationClasses::new(vec![kerberos_auth_class()]), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - Some("tls".parse().unwrap()), - None, - ) - } - - /// Internal TLS only (broker/controller encryption without client TLS). - fn internal_tls() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - no_auth(), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - None, - None, - ) - } - - /// OPA authorization with a TLS truststore (internal + server TLS also enabled). - fn opa() -> ValidatedKafkaSecurity { - ValidatedKafkaSecurity::new( - no_auth(), - SecretClassName::from_str("tls").expect("tls secret class name is valid"), - Some("tls".parse().unwrap()), - Some("opa-tls".parse().unwrap()), - ) - } + use crate::controller::test_support::{ + client_auth_tls, internal_tls, kerberos, opa, plaintext, server_tls, + }; fn as_str_vec(commands: &[String]) -> Vec<&str> { commands.iter().map(String::as_str).collect() diff --git a/rust/operator-binary/src/controller/security.rs b/rust/operator-binary/src/controller/security.rs index 90bd62178..a97c732f2 100644 --- a/rust/operator-binary/src/controller/security.rs +++ b/rust/operator-binary/src/controller/security.rs @@ -101,6 +101,18 @@ impl ValidatedKafkaSecurity { .get_tls_authentication_class() } + /// The `SecretClass` of a TLS `AuthenticationClass`, otherwise the server `SecretClass`. + pub fn tls_secret_class(&self) -> Option<&str> { + self.tls_client_authentication_class() + .and_then(|auth_class| match &auth_class.spec.provider { + core::v1alpha1::AuthenticationClassProvider::Tls(tls) => { + tls.client_cert_secret_class.as_deref() + } + _ => None, + }) + .or_else(|| self.tls_server_secret_class()) + } + /// Retrieve the internal `SecretClass`. Internal (inter-broker) TLS is mandatory, so this is /// always set (defaults to `tls`). pub fn tls_internal_secret_class(&self) -> &str { diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index 1280baf0b..6d91613ed 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -24,14 +24,15 @@ use stackable_operator::{ validate_logging_configuration_for_container, }, role_utils::{JavaCommonConfig, Role, with_validated_config}, - types::kubernetes::ConfigMapName, + types::kubernetes::{ConfigMapName, SecretClassName}, }, }; use crate::{ controller::{ - RoleGroupName, ValidatedAgentConfig, ValidatedCluster, ValidatedClusterConfig, - ValidatedKafkaConfig, ValidatedRoleConfig, ValidatedRoleGroupConfig, + AgentConnection, RoleGroupName, ValidatedAgentConfig, ValidatedCluster, + ValidatedClusterConfig, ValidatedKafkaConfig, ValidatedRoleConfig, + ValidatedRoleGroupConfig, dereference::DereferencedObjects, security::{self, ValidatedKafkaSecurity}, }, @@ -135,6 +136,12 @@ pub enum Error { #[snafu(display("TLS management access requires the cluster to use TLS"))] TlsManagementAccessRequiresTls, + + #[snafu(display("the SecretClass {secret_class:?} of the client listener is invalid"))] + ParseClientListenerSecretClass { + source: stackable_operator::v2::macros::attributed_string_type::Error, + secret_class: String, + }, } /// Validated logging configuration for a Kafka role group's Kafka and (optional) Vector @@ -369,15 +376,14 @@ pub fn validate( metadata_manager == crate::crd::MetadataManager::KRaft, ManagementAccessRequiresKraftSnafu ); - validate_management_access( - &management_access.authentication.user_provided, - &kafka_security, - )?; Ok(ValidatedAgentConfig { image: operator_image .context(ManagementAccessRequiresOperatorImageSnafu)? .to_owned(), - authentication: management_access.authentication.user_provided.clone(), + connection: validate_agent_connection( + &management_access.authentication.user_provided, + &kafka_security, + )?, }) }) .transpose()?; @@ -490,27 +496,49 @@ fn inject_cluster_id(env_overrides: EnvVarSet, cluster_id: Option<&str>) -> EnvV } } -/// Rejects management access authentication config that cannot connect to the cluster. -fn validate_management_access( +/// Determines how the agent connects to the cluster, and rejects management access authentication +/// config that cannot connect to it. +fn validate_agent_connection( authentication: &v1alpha1::UserProvidedAuthentication, security: &ValidatedKafkaSecurity, -) -> Result<()> { +) -> Result { ensure!( !security.has_kerberos_enabled(), ManagementAccessWithKerberosSnafu ); - match authentication { - v1alpha1::UserProvidedAuthentication::Anonymous(_) => ensure!( - security.tls_client_authentication_class().is_none(), - AnonymousManagementAccessWithClientAuthenticationSnafu - ), - v1alpha1::UserProvidedAuthentication::Tls(_) => { - ensure!(security.tls_enabled(), TlsManagementAccessRequiresTlsSnafu) + let server_ca_secret_class = security + .tls_secret_class() + .map(|secret_class| { + SecretClassName::from_str(secret_class) + .context(ParseClientListenerSecretClassSnafu { secret_class }) + }) + .transpose()?; + + match (authentication, server_ca_secret_class) { + (v1alpha1::UserProvidedAuthentication::Anonymous(_), server_ca_secret_class) => { + ensure!( + security.tls_client_authentication_class().is_none(), + AnonymousManagementAccessWithClientAuthenticationSnafu + ); + Ok(match server_ca_secret_class { + None => AgentConnection::Plaintext, + Some(server_ca_secret_class) => AgentConnection::Tls { + server_ca_secret_class, + }, + }) + } + (v1alpha1::UserProvidedAuthentication::Tls(_), None) => { + TlsManagementAccessRequiresTlsSnafu.fail() } + ( + v1alpha1::UserProvidedAuthentication::Tls(client_credential), + Some(server_ca_secret_class), + ) => Ok(AgentConnection::MutualTls { + server_ca_secret_class, + client_credential: client_credential.clone(), + }), } - - Ok(()) } #[cfg(test)] @@ -522,13 +550,17 @@ mod tests { crd::management_access::v1alpha1::{Anonymous, TlsClientCredential}, v2::{ builder::pod::container::EnvVarSet, - types::{kubernetes::SecretName, operator::RoleGroupName}, + types::{ + kubernetes::{SecretClassName, SecretName}, + operator::RoleGroupName, + }, }, }; - use super::{Error, KAFKA_CLUSTER_ID, inject_cluster_id, validate_management_access}; + use super::{Error, KAFKA_CLUSTER_ID, inject_cluster_id, validate_agent_connection}; use crate::{ controller::{ + AgentConnection, security::ValidatedKafkaSecurity, test_support::{ app_version_label, client_auth_tls, kerberos, minimal_kafka, plaintext, server_tls, @@ -542,30 +574,59 @@ mod tests { UserProvidedAuthentication::Anonymous(Anonymous::default()) } - fn tls() -> UserProvidedAuthentication { - UserProvidedAuthentication::Tls(TlsClientCredential::SecretName( + fn agent_cert() -> TlsClientCredential { + TlsClientCredential::SecretName( SecretName::from_str("agent-cert").expect("the Secret name should be valid"), - )) + ) + } + + fn tls() -> UserProvidedAuthentication { + UserProvidedAuthentication::Tls(agent_cert()) + } + + fn tls_secret_class(name: &str) -> SecretClassName { + SecretClassName::from_str(name).expect("the SecretClass name should be valid") } #[rstest] - #[case::plaintext_anonymous(plaintext(), anonymous())] - #[case::server_tls_anonymous(server_tls(), anonymous())] - #[case::server_tls_with_credential(server_tls(), tls())] - #[case::client_auth_with_credential(client_auth_tls(), tls())] - fn accept_management_access( + #[case::plaintext_anonymous(plaintext(), anonymous(), AgentConnection::Plaintext)] + #[case::server_tls_anonymous( + server_tls(), + anonymous(), + AgentConnection::Tls { server_ca_secret_class: tls_secret_class("tls") } + )] + #[case::server_tls_with_credential( + server_tls(), + tls(), + AgentConnection::MutualTls { + server_ca_secret_class: tls_secret_class("tls"), + client_credential: agent_cert(), + } + )] + #[case::client_auth_with_credential( + client_auth_tls(), + tls(), + AgentConnection::MutualTls { + server_ca_secret_class: tls_secret_class("client-auth-secret-class"), + client_credential: agent_cert(), + } + )] + fn agent_connection( #[case] security: ValidatedKafkaSecurity, #[case] authentication: UserProvidedAuthentication, + #[case] expected: AgentConnection, ) { - validate_management_access(&authentication, &security) + let connection = validate_agent_connection(&authentication, &security) .expect("the management access should be valid"); + + assert_eq!(expected, connection); } #[rstest] #[case::anonymous(anonymous())] #[case::tls(tls())] fn reject_management_access_with_kerberos(#[case] authentication: UserProvidedAuthentication) { - let error = validate_management_access(&authentication, &kerberos()) + let error = validate_agent_connection(&authentication, &kerberos()) .expect_err("the management access should be invalid"); assert!(matches!(error, Error::ManagementAccessWithKerberos)); @@ -573,7 +634,7 @@ mod tests { #[test] fn reject_anonymous_management_access_with_client_authentication() { - let error = validate_management_access(&anonymous(), &client_auth_tls()) + let error = validate_agent_connection(&anonymous(), &client_auth_tls()) .expect_err("the management access should be invalid"); assert!(matches!( @@ -584,7 +645,7 @@ mod tests { #[test] fn reject_tls_management_access_without_tls() { - let error = validate_management_access(&tls(), &plaintext()) + let error = validate_agent_connection(&tls(), &plaintext()) .expect_err("the management access should be invalid"); assert!(matches!(error, Error::TlsManagementAccessRequiresTls)); diff --git a/rust/shared/Cargo.toml b/rust/shared/Cargo.toml new file mode 100644 index 000000000..a26223f1c --- /dev/null +++ b/rust/shared/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "stackable-kafka-shared" +description = "Types and contracts shared by the Stackable operator and agent for Apache Kafka" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +publish = false + +[dependencies] +stackable-operator.workspace = true + +strum.workspace = true + +[dev-dependencies] +rstest.workspace = true diff --git a/rust/shared/src/agent.rs b/rust/shared/src/agent.rs new file mode 100644 index 000000000..617360172 --- /dev/null +++ b/rust/shared/src/agent.rs @@ -0,0 +1,42 @@ +//! Paths and environment variables through which the operator configures the agent. + +use std::str::FromStr; + +use stackable_operator::{constant, v2::builder::pod::container::EnvVarName}; +use strum::{Display, EnumString}; + +pub const DISCOVERY_DIR: &str = "/stackable/discovery"; + +/// Directory of the CA certificate the Kafka brokers are verified with. +pub const KAFKA_TLS_DIR: &str = "/stackable/secrets/tls-kafka"; + +constant!(pub ENV_CLUSTER_NAME: EnvVarName = "KAFKA_CLUSTER_NAME"); +constant!(pub ENV_CLUSTER_NAMESPACE: EnvVarName = "KAFKA_CLUSTER_NAMESPACE"); +constant!(pub ENV_CLIENT_SECURITY: EnvVarName = "KAFKA_CLIENT_SECURITY"); + +/// How the agent connects to the brokers. +#[derive(Clone, Copy, Debug, Display, EnumString, Eq, PartialEq)] +#[strum(serialize_all = "kebab-case")] +pub enum ClientSecurity { + Plaintext, + Tls, + MutualTls, +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use rstest::rstest; + + use super::*; + + #[rstest] + #[case::plaintext(ClientSecurity::Plaintext, "plaintext")] + #[case::tls(ClientSecurity::Tls, "tls")] + #[case::mutual_tls(ClientSecurity::MutualTls, "mutual-tls")] + fn roundtrip(#[case] security: ClientSecurity, #[case] value: &str) { + assert_eq!(value, security.to_string()); + assert_eq!(Ok(security), ClientSecurity::from_str(value)); + } +} diff --git a/rust/shared/src/lib.rs b/rust/shared/src/lib.rs new file mode 100644 index 000000000..f17bc55db --- /dev/null +++ b/rust/shared/src/lib.rs @@ -0,0 +1 @@ +pub mod agent; From 87a290eb566deda46e36e3f0d6c9d5eb560a5a00 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Mon, 26 Oct 2026 11:30:18 +0100 Subject: [PATCH 16/25] use AgentResourceNames from operator-rs --- Cargo.lock | 18 +++--- Cargo.nix | 18 +++--- rust/operator-binary/src/controller.rs | 9 +++ .../src/controller/build/resource/agent.rs | 59 +++++++------------ .../controller/build/resource/statefulset.rs | 1 + rust/operator-binary/src/main.rs | 2 +- 6 files changed, 49 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f092e03d4..12e294d61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.4" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "darling 0.24.1", "regex", @@ -3168,7 +3168,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "const-oid", "ecdsa", @@ -3235,7 +3235,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.121.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "base64 0.23.1", "clap", @@ -3279,7 +3279,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3290,7 +3290,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.2.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "jiff", "k8s-openapi", @@ -3307,7 +3307,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "axum", "clap", @@ -3331,7 +3331,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "kube", "schemars", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "convert_case", "darling 0.24.1", @@ -3361,7 +3361,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#a2a7d0caf7b00c332cd299768eea19b1a3a00a51" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index e3bd3c098..3494b58fe 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5455,7 +5455,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "k8s_version"; @@ -10388,7 +10388,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_certs"; @@ -10660,7 +10660,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_operator"; @@ -10859,7 +10859,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -10894,7 +10894,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_shared"; @@ -10975,7 +10975,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_telemetry"; @@ -11085,7 +11085,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_versioned"; @@ -11131,7 +11131,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; procMacro = true; @@ -11195,7 +11195,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "a2a7d0caf7b00c332cd299768eea19b1a3a00a51"; + rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; }; libName = "stackable_webhook"; diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 368bbdf2b..82ff790a2 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -38,6 +38,7 @@ use stackable_operator::{ shared::time::Duration, v2::{ HasName, HasUid, NameIsValidLabelValue, + agent_utils::AgentResourceNames, role_group_utils::ResourceNames, role_utils, types::{ @@ -263,6 +264,14 @@ impl ValidatedCluster { } } + /// Type-safe names for the resources of the agent. + pub fn agent_resource_names(&self) -> AgentResourceNames { + AgentResourceNames { + cluster_name: self.name.clone(), + product_name: PRODUCT_NAME.clone(), + } + } + /// Type-safe names for the resources of a given role group. pub(crate) fn role_group_resource_names( &self, diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 19fcd4332..0f288f964 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -20,20 +20,19 @@ use stackable_operator::{ commons::secret_class::SecretClassVolumeProvisionParts, constant, k8s_openapi::{ - Resource, api::{ apps::v1::{Deployment, DeploymentSpec, DeploymentStrategy}, core::v1::{EnvVar, EnvVarSource, ObjectFieldSelector, ServiceAccount}, - rbac::v1::{ClusterRole, RoleBinding, RoleRef, Subject}, + rbac::v1::RoleBinding, }, apimachinery::pkg::apis::meta::v1::LabelSelector, }, - kube::api::ObjectMeta, v2::{ builder::{ meta::ownerreference_from_resource, pod::container::{EnvVarName, EnvVarSet, new_container_builder}, }, + rbac::{self, RbacResourceNames}, types::kubernetes::{ContainerName, SecretClassName, VolumeName}, }, }; @@ -48,12 +47,12 @@ constant!(DISCOVERY_VOLUME_NAME: VolumeName = "discovery"); constant!(KAFKA_TLS_VOLUME_NAME: VolumeName = "tls-kafka"); constant!(KUBERNETES_NODE_NAME: EnvVarName = "KUBERNETES_NODE_NAME"); constant!(KUBERNETES_CLUSTER_DOMAIN: EnvVarName = "KUBERNETES_CLUSTER_DOMAIN"); -pub const AGENT_CLUSTER_ROLE_NAME: &str = "kafka-agent-clusterrole"; pub fn build_agent_deployment( cluster: &ValidatedCluster, agent_config: &ValidatedAgentConfig, ) -> Deployment { + let resource_names = cluster.agent_resource_names(); let mut cb_agent = new_container_builder(&AGENT_CONTAINER_NAME); let mut pod_builder = PodBuilder::new(); @@ -100,7 +99,7 @@ pub fn build_agent_deployment( ) .image_pull_secrets_from_product_image(&cluster.image) .add_container(cb_agent.build()) - .service_account_name(agent_name(cluster)) + .service_account_name(resource_names.service_account_name().to_string()) .security_context( PodSecurityContextBuilder::with_stackable_defaults() .fs_group(1000) @@ -108,7 +107,12 @@ pub fn build_agent_deployment( ); Deployment { - metadata: agent_metadata(cluster), + metadata: ObjectMetaBuilder::new() + .name_and_namespace(cluster) + .name(resource_names.deployment_name().to_string()) + .ownerreference(ownerreference_from_resource(cluster, None, Some(true))) + .with_labels(recommended_labels_for_agent_resources(cluster)) + .build(), spec: Some(DeploymentSpec { replicas: Some(1), // Never run two agents at the same time, as for the operator itself. @@ -128,28 +132,20 @@ pub fn build_agent_deployment( } pub fn build_agent_service_account(cluster: &ValidatedCluster) -> ServiceAccount { - ServiceAccount { - metadata: agent_metadata(cluster), - ..ServiceAccount::default() - } + rbac::build_service_account( + cluster, + &cluster.agent_resource_names(), + recommended_labels_for_agent_resources(cluster), + ) } /// Binds the agent ServiceAccount to the agent ClusterRole deployed by the Helm chart. pub fn build_agent_role_binding(cluster: &ValidatedCluster) -> RoleBinding { - RoleBinding { - metadata: agent_metadata(cluster), - role_ref: RoleRef { - api_group: Some(ClusterRole::GROUP.to_owned()), - kind: ClusterRole::KIND.to_owned(), - name: AGENT_CLUSTER_ROLE_NAME.to_owned(), - }, - subjects: Some(vec![Subject { - kind: ServiceAccount::KIND.to_owned(), - name: agent_name(cluster), - namespace: Some(cluster.namespace.to_string()), - ..Subject::default() - }]), - } + rbac::build_role_binding( + cluster, + &cluster.agent_resource_names(), + recommended_labels_for_agent_resources(cluster), + ) } fn agent_env_vars(cluster: &ValidatedCluster, agent_config: &ValidatedAgentConfig) -> EnvVarSet { @@ -226,21 +222,6 @@ fn add_kafka_tls_volume_and_mount( .expect("the mount path is statically defined and must not collide"); } -/// The name of all agent resources. Kinds don't share a namespace, so unlike a suffix per kind, this -/// cannot collide with the resources of a cluster named `-agent`. -fn agent_name(cluster: &ValidatedCluster) -> String { - format!("{}-agent", cluster.name) -} - -fn agent_metadata(cluster: &ValidatedCluster) -> ObjectMeta { - ObjectMetaBuilder::new() - .name_and_namespace(cluster) - .name(agent_name(cluster)) - .ownerreference(ownerreference_from_resource(cluster, None, Some(true))) - .with_labels(recommended_labels_for_agent_resources(cluster)) - .build() -} - #[cfg(test)] mod tests { use serde_json::{Value, json}; diff --git a/rust/operator-binary/src/controller/build/resource/statefulset.rs b/rust/operator-binary/src/controller/build/resource/statefulset.rs index ed56b0928..b0da6a2de 100644 --- a/rust/operator-binary/src/controller/build/resource/statefulset.rs +++ b/rust/operator-binary/src/controller/build/resource/statefulset.rs @@ -35,6 +35,7 @@ use stackable_operator::{ product_logging::framework::{ STACKABLE_LOG_DIR, ValidatedContainerLogConfigChoice, vector_container, }, + rbac::RbacResourceNames, role_group_utils::ResourceNames, types::kubernetes::{ConfigMapKey, ContainerName, VolumeName}, }, diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 8ef5b8398..73367def6 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -69,7 +69,7 @@ struct KafkaRun { #[clap(flatten)] common: RunArguments, - /// The image of this operator, which also contains the agent. Required to enable platform + /// The image of this operator, which also contains the agent. Required to enable management /// access on a KafkaCluster. #[arg(long, env)] operator_image: Option, From 61b1005ae663fcfd0c74d72394ac38bf284dba02 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 09:01:23 +0100 Subject: [PATCH 17/25] update operator-rs --- Cargo.lock | 31 +++++++++++----- Cargo.nix | 95 +++++++++++++++++++++++++++++++++++------------ Cargo.toml | 2 +- crate-hashes.json | 19 +++++----- 4 files changed, 105 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12e294d61..1c2030e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.4" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "darling 0.24.1", "regex", @@ -3165,10 +3165,22 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "stackable-agent" +version = "0.1.0" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +dependencies = [ + "k8s-openapi", + "schemars", + "serde", + "stackable-versioned", + "strum", +] + [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "const-oid", "ecdsa", @@ -3235,7 +3247,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.121.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "base64 0.23.1", "clap", @@ -3260,6 +3272,7 @@ dependencies = [ "serde_json", "sha2", "snafu 0.9.2", + "stackable-agent", "stackable-operator-derive", "stackable-shared", "stackable-telemetry", @@ -3279,7 +3292,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3290,7 +3303,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.2.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "jiff", "k8s-openapi", @@ -3307,7 +3320,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "axum", "clap", @@ -3331,7 +3344,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "kube", "schemars", @@ -3344,7 +3357,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "convert_case", "darling 0.24.1", @@ -3361,7 +3374,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#079f7413186c44b0bf9723c1361ea955613c39b1" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 3494b58fe..416da7837 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5455,8 +5455,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "k8s_version"; authors = [ @@ -10381,6 +10381,49 @@ rec { "std" = [ "alloc" ]; }; }; + "stackable-agent" = rec { + crateName = "stackable-agent"; + version = "0.1.0"; + edition = "2024"; + workspace_member = null; + src = pkgs.fetchgit { + url = "https://github.com/stackabletech/operator-rs.git"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + }; + libName = "stackable_agent"; + authors = [ + "Stackable GmbH " + ]; + dependencies = [ + { + name = "k8s-openapi"; + packageId = "k8s-openapi"; + usesDefaultFeatures = false; + features = [ "schemars" "v1_36" ]; + } + { + name = "schemars"; + packageId = "schemars"; + features = [ "url2" ]; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "stackable-versioned"; + packageId = "stackable-versioned"; + } + { + name = "strum"; + packageId = "strum"; + features = [ "derive" ]; + } + ]; + + }; "stackable-certs" = rec { crateName = "stackable-certs"; version = "0.4.1"; @@ -10388,8 +10431,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_certs"; authors = [ @@ -10511,7 +10554,7 @@ rec { { name = "stackable-operator"; packageId = "stackable-operator"; - features = [ "crds" "webhook" ]; + features = [ "agent" "crds" "webhook" ]; } { name = "tokio"; @@ -10592,7 +10635,7 @@ rec { { name = "stackable-operator"; packageId = "stackable-operator"; - features = [ "crds" "webhook" ]; + features = [ "agent" "crds" "webhook" ]; } { name = "strum"; @@ -10637,7 +10680,7 @@ rec { { name = "stackable-operator"; packageId = "stackable-operator"; - features = [ "crds" "webhook" ]; + features = [ "agent" "crds" "webhook" ]; } { name = "strum"; @@ -10660,8 +10703,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_operator"; authors = [ @@ -10772,6 +10815,11 @@ rec { name = "snafu"; packageId = "snafu 0.9.2"; } + { + name = "stackable-agent"; + packageId = "stackable-agent"; + optional = true; + } { name = "stackable-operator-derive"; packageId = "stackable-operator-derive"; @@ -10838,11 +10886,12 @@ rec { } ]; features = { + "agent" = [ "dep:stackable-agent" ]; "certs" = [ "dep:stackable-certs" ]; "client-feature-gates" = [ "dep:winnow" ]; "crds" = [ "dep:stackable-versioned" ]; "default" = [ "crds" ]; - "full" = [ "client-feature-gates" "crds" "certs" "test-support" "time" "webhook" "kube-ws" "kube-cel" "kube-http-proxy" "kube-socks5" ]; + "full" = [ "agent" "client-feature-gates" "crds" "certs" "test-support" "time" "webhook" "kube-ws" "kube-cel" "kube-http-proxy" "kube-socks5" ]; "kube-cel" = [ "kube/cel" ]; "kube-http-proxy" = [ "kube/http-proxy" ]; "kube-socks5" = [ "kube/socks5" ]; @@ -10850,7 +10899,7 @@ rec { "time" = [ "stackable-shared/time" ]; "webhook" = [ "dep:stackable-webhook" ]; }; - resolvedDefaultFeatures = [ "crds" "default" "webhook" ]; + resolvedDefaultFeatures = [ "agent" "crds" "default" "webhook" ]; }; "stackable-operator-derive" = rec { crateName = "stackable-operator-derive"; @@ -10859,8 +10908,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10894,8 +10943,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_shared"; authors = [ @@ -10975,8 +11024,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_telemetry"; authors = [ @@ -11085,8 +11134,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_versioned"; authors = [ @@ -11131,8 +11180,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11195,8 +11244,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "079f7413186c44b0bf9723c1361ea955613c39b1"; - sha256 = "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci"; + rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_webhook"; authors = [ diff --git a/Cargo.toml b/Cargo.toml index 81beda9ec..ae973805a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" repository = "https://github.com/stackabletech/kafka-operator" [workspace.dependencies] -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", branch = "feat/platform-access", features = ["crds", "webhook"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", branch = "feat/platform-access", features = ["agent", "crds", "webhook"] } stackable-kafka-shared = { path = "rust/shared" } anyhow = "1.0" diff --git a/crate-hashes.json b/crate-hashes.json index a5ee97020..017105d5a 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,11 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0cgziqra8097hp05ynib1qpw4c95n972f4w2rk9l3llyp8r1vmci" + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm" } \ No newline at end of file From 66bf00b3c793146f015618205db72f828b356eee Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 11:32:09 +0100 Subject: [PATCH 18/25] replace hard-coded selectors on agent deployment with util from operator-rs --- Cargo.lock | 20 ++++++++++---------- Cargo.nix | 20 ++++++++++---------- rust/operator-binary/src/controller.rs | 8 +++++++- rust/operator-binary/src/main.rs | 6 ++---- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c2030e7a..288c23de1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.4" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "darling 0.24.1", "regex", @@ -3168,7 +3168,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-agent" version = "0.1.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "k8s-openapi", "schemars", @@ -3180,7 +3180,7 @@ dependencies = [ [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "const-oid", "ecdsa", @@ -3247,7 +3247,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.121.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "base64 0.23.1", "clap", @@ -3292,7 +3292,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3303,7 +3303,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.2.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "jiff", "k8s-openapi", @@ -3320,7 +3320,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "axum", "clap", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "kube", "schemars", @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "convert_case", "darling 0.24.1", @@ -3374,7 +3374,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b815f203fda98c109be46aa67e7cf3921c808603" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 416da7837..0529432e5 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5455,7 +5455,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "k8s_version"; @@ -10388,7 +10388,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_agent"; @@ -10431,7 +10431,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_certs"; @@ -10703,7 +10703,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_operator"; @@ -10908,7 +10908,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; procMacro = true; @@ -10943,7 +10943,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_shared"; @@ -11024,7 +11024,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_telemetry"; @@ -11134,7 +11134,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_versioned"; @@ -11180,7 +11180,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; procMacro = true; @@ -11244,7 +11244,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "b815f203fda98c109be46aa67e7cf3921c808603"; + rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; }; libName = "stackable_webhook"; diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 82ff790a2..b9618ede8 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -31,7 +31,7 @@ use stackable_operator::{ kube::{ Resource, api::{DynamicObject, ObjectMeta}, - core::{DeserializeGuard, error_boundary}, + core::{DeserializeGuard, Selector, error_boundary}, runtime::{controller::Action, reflector::ObjectRef}, }, logging::controller::ReconcilerError, @@ -39,6 +39,7 @@ use stackable_operator::{ v2::{ HasName, HasUid, NameIsValidLabelValue, agent_utils::AgentResourceNames, + kvp::label, role_group_utils::ResourceNames, role_utils, types::{ @@ -82,6 +83,11 @@ constant!(PRODUCT_NAME: ProductName = APP_NAME); constant!(OPERATOR_NAME: OperatorName = KAFKA_OPERATOR_NAME); constant!(CONTROLLER_NAME: ControllerName = KAFKA_CONTROLLER_NAME); +/// Selector matching the agents of all KafkaClusters, e.g. to watch them. +pub fn all_agents_selector() -> Selector { + Selector::from_iter(BTreeMap::from(label::all_agents_selector(&PRODUCT_NAME))) +} + #[derive(Snafu, Debug)] pub enum PodDescriptorsError { #[snafu(display( diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 73367def6..7a0a9c5f9 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -37,7 +37,7 @@ use stackable_operator::{ }; use crate::{ - controller::KAFKA_FULL_CONTROLLER_NAME, + controller::{KAFKA_FULL_CONTROLLER_NAME, all_agents_selector}, crd::{KAFKA_OPERATOR_NAME, KafkaCluster, KafkaClusterVersion, v1alpha1}, webhooks::conversion::create_webhook_server, }; @@ -187,9 +187,7 @@ async fn main() -> anyhow::Result<()> { .owns( watch_namespace.get_api::>(&client), // The agent is the only Deployment - watcher::Config::default().labels( - "app.kubernetes.io/name=kafka,app.kubernetes.io/component=kafka-agent", - ), + watcher::Config::default().labels_from(&all_agents_selector()), ) .watches( watch_namespace.get_api::>(&client), From 14f9ee81698d3b305006b0e5672d82dfcdc25b9e Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 14:21:16 +0100 Subject: [PATCH 19/25] use headless service to connect to bootstrap servers --- .../controller/build/properties/listener.rs | 19 ++++- .../src/controller/build/properties/mod.rs | 11 ++- .../src/controller/build/resource/agent.rs | 80 +++++++++++-------- rust/shared/src/agent.rs | 4 +- 4 files changed, 71 insertions(+), 43 deletions(-) diff --git a/rust/operator-binary/src/controller/build/properties/listener.rs b/rust/operator-binary/src/controller/build/properties/listener.rs index acc632558..2cb533769 100644 --- a/rust/operator-binary/src/controller/build/properties/listener.rs +++ b/rust/operator-binary/src/controller/build/properties/listener.rs @@ -6,7 +6,13 @@ use std::collections::BTreeMap; -use stackable_operator::{commons::networking::DomainName, v2::types::kubernetes::NamespaceName}; +use stackable_operator::{ + commons::networking::DomainName, + v2::types::{ + common::Port, + kubernetes::{NamespaceName, ServiceName}, + }, +}; use crate::{ controller::{RoleGroupName, ValidatedCluster, security::ValidatedKafkaSecurity}, @@ -151,6 +157,17 @@ pub(crate) fn pod_fqdn( format!("${{env:POD_NAME}}.{sts_service_name}.{namespace}.svc.{cluster_domain}") } +/// `..svc.:`, which resolves to the Pods of a headless +/// Service. +pub(crate) fn headless_service_address( + headless_service_name: &ServiceName, + namespace: &NamespaceName, + cluster_domain: &DomainName, + port: &Port, +) -> String { + format!("{headless_service_name}.{namespace}.svc.{cluster_domain}:{port}") +} + #[cfg(test)] mod tests { use stackable_operator::{ diff --git a/rust/operator-binary/src/controller/build/properties/mod.rs b/rust/operator-binary/src/controller/build/properties/mod.rs index e751613aa..708c121ee 100644 --- a/rust/operator-binary/src/controller/build/properties/mod.rs +++ b/rust/operator-binary/src/controller/build/properties/mod.rs @@ -103,12 +103,11 @@ pub(crate) fn kraft_controllers( client_port = desc.client_port, ) } else { - format!( - "{service}.{namespace}.svc.{cluster_domain}:{client_port}", - service = desc.role_group_service_name, - namespace = desc.namespace, - cluster_domain = desc.cluster_domain, - client_port = desc.client_port, + listener::headless_service_address( + &desc.role_group_service_name, + &desc.namespace, + &desc.cluster_domain, + &desc.client_port, ) } }) diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 0f288f964..00cc65c65 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -3,8 +3,8 @@ use std::str::FromStr; use stackable_kafka_shared::agent::{ - ClientSecurity, DISCOVERY_DIR, ENV_CLIENT_SECURITY, ENV_CLUSTER_NAME, ENV_CLUSTER_NAMESPACE, - KAFKA_TLS_DIR, + ClientSecurity, ENV_BOOTSTRAP_SERVERS, ENV_CLIENT_SECURITY, ENV_CLUSTER_NAME, + ENV_CLUSTER_NAMESPACE, KAFKA_TLS_DIR, }; use stackable_operator::{ builder::{ @@ -37,13 +37,18 @@ use stackable_operator::{ }, }; -use crate::controller::{ - AgentConnection, ValidatedAgentConfig, ValidatedCluster, - build::{agent_selector, recommended_labels_for_agent_resources}, +use crate::{ + controller::{ + AgentConnection, ValidatedAgentConfig, ValidatedCluster, + build::{ + agent_selector, properties::listener::headless_service_address, + recommended_labels_for_agent_resources, + }, + }, + crd::role::KafkaRole, }; constant!(AGENT_CONTAINER_NAME: ContainerName = "agent"); -constant!(DISCOVERY_VOLUME_NAME: VolumeName = "discovery"); constant!(KAFKA_TLS_VOLUME_NAME: VolumeName = "tls-kafka"); constant!(KUBERNETES_NODE_NAME: EnvVarName = "KUBERNETES_NODE_NAME"); constant!(KUBERNETES_CLUSTER_DOMAIN: EnvVarName = "KUBERNETES_CLUSTER_DOMAIN"); @@ -56,7 +61,6 @@ pub fn build_agent_deployment( let mut cb_agent = new_container_builder(&AGENT_CONTAINER_NAME); let mut pod_builder = PodBuilder::new(); - add_discovery_volume_and_mount(cluster, &mut pod_builder, &mut cb_agent); match &agent_config.connection { AgentConnection::Plaintext => {} AgentConnection::Tls { @@ -162,6 +166,7 @@ fn agent_env_vars(cluster: &ValidatedCluster, agent_config: &ValidatedAgentConfi }; EnvVarSet::new() + .with_value(&ENV_BOOTSTRAP_SERVERS, bootstrap_servers(cluster)) .with_value(&ENV_CLUSTER_NAME, cluster.name.to_string()) .with_value(&ENV_CLUSTER_NAMESPACE, cluster.namespace.to_string()) .with_value( @@ -177,21 +182,30 @@ fn agent_env_vars(cluster: &ValidatedCluster, agent_config: &ValidatedAgentConfi .expect("the env var name is a valid EnvVarName") } -fn add_discovery_volume_and_mount( - cluster: &ValidatedCluster, - pod_builder: &mut PodBuilder, - container_builder: &mut ContainerBuilder, -) { - pod_builder - .add_volume( - VolumeBuilder::new(&*DISCOVERY_VOLUME_NAME) - .with_config_map(cluster.name.to_string()) - .build(), - ) - .expect("the volume name is statically defined and must not collide"); - container_builder - .add_volume_mount(&*DISCOVERY_VOLUME_NAME, DISCOVERY_DIR) - .expect("the mount path is statically defined and must not collide"); +/// The headless Services of the broker role groups, which resolve to the broker Pods. +/// +/// They keep the traffic within the Kubernetes cluster regardless of the ListenerClass. The pod +/// scope of the broker certificates puts them into the SANs, so hostname verification passes. The +/// agent stays on the bootstrap connection, so it never follows the advertised addresses. +fn bootstrap_servers(cluster: &ValidatedCluster) -> String { + let client_port = cluster.cluster_config.kafka_security.client_port(); + cluster + .role_group_configs + .get(&KafkaRole::Broker) + .into_iter() + .flat_map(|role_group_configs| role_group_configs.keys()) + .map(|role_group_name| { + headless_service_address( + &cluster + .role_group_resource_names(&KafkaRole::Broker, role_group_name) + .headless_service_name(), + &cluster.namespace, + &cluster.cluster_domain, + &client_port, + ) + }) + .collect::>() + .join(",") } fn add_kafka_tls_volume_and_mount( @@ -333,28 +347,27 @@ mod tests { assert_eq!( pod_spec["containers"][0]["volumeMounts"], json!([ - {"mountPath": "/stackable/discovery", "name": "discovery"}, {"mountPath": "/stackable/secrets/tls-kafka", "name": "tls-kafka"}, {"mountPath": "/stackable/secrets/tls-management-access", "name": "tls-management-access"} ]) ); assert_eq!( - pod_spec["volumes"][0]["configMap"], - json!({"name": "simple-kafka"}) - ); - assert_eq!( - pod_spec["volumes"][1]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"], + pod_spec["volumes"][0]["ephemeral"]["volumeClaimTemplate"]["metadata"]["annotations"], json!({ "secrets.stackable.tech/class": "tls", "secrets.stackable.tech/format": "tls-pem", "secrets.stackable.tech/provision-parts": "public" }) ); - assert_eq!(pod_spec["volumes"][2]["name"], "tls-management-access"); + assert_eq!(pod_spec["volumes"][1]["name"], "tls-management-access"); assert_eq!( pod_spec["containers"][0]["env"], json!([ + { + "name": "KAFKA_BOOTSTRAP_SERVERS", + "value": "simple-kafka-broker-default-headless.default.svc.cluster.local:9093" + }, {"name": "KAFKA_CLIENT_SECURITY", "value": "mutual-tls"}, {"name": "KAFKA_CLUSTER_NAME", "value": "simple-kafka"}, {"name": "KAFKA_CLUSTER_NAMESPACE", "value": "default"}, @@ -374,7 +387,7 @@ mod tests { )); assert_eq!( - deployment["spec"]["template"]["spec"]["volumes"][2], + deployment["spec"]["template"]["spec"]["volumes"][1], json!({"name": "tls-management-access", "secret": {"optional": false, "secretName": "my-cert"}}) ); } @@ -386,11 +399,10 @@ mod tests { )); let pod_spec = &deployment["spec"]["template"]["spec"]; - assert_eq!(pod_spec["volumes"][0]["name"], "discovery"); - assert_eq!(pod_spec["volumes"][1]["name"], "tls-kafka"); - assert_eq!(pod_spec["volumes"][2], Value::Null); + assert_eq!(pod_spec["volumes"][0]["name"], "tls-kafka"); + assert_eq!(pod_spec["volumes"][1], Value::Null); assert_eq!( - pod_spec["containers"][0]["env"][0], + pod_spec["containers"][0]["env"][1], json!({"name": "KAFKA_CLIENT_SECURITY", "value": "tls"}) ); } diff --git a/rust/shared/src/agent.rs b/rust/shared/src/agent.rs index 617360172..c50170e06 100644 --- a/rust/shared/src/agent.rs +++ b/rust/shared/src/agent.rs @@ -5,14 +5,14 @@ use std::str::FromStr; use stackable_operator::{constant, v2::builder::pod::container::EnvVarName}; use strum::{Display, EnumString}; -pub const DISCOVERY_DIR: &str = "/stackable/discovery"; - /// Directory of the CA certificate the Kafka brokers are verified with. pub const KAFKA_TLS_DIR: &str = "/stackable/secrets/tls-kafka"; constant!(pub ENV_CLUSTER_NAME: EnvVarName = "KAFKA_CLUSTER_NAME"); constant!(pub ENV_CLUSTER_NAMESPACE: EnvVarName = "KAFKA_CLUSTER_NAMESPACE"); constant!(pub ENV_CLIENT_SECURITY: EnvVarName = "KAFKA_CLIENT_SECURITY"); +// Comma-separated `host:port` list +constant!(pub ENV_BOOTSTRAP_SERVERS: EnvVarName = "KAFKA_BOOTSTRAP_SERVERS"); /// How the agent connects to the brokers. #[derive(Clone, Copy, Debug, Display, EnumString, Eq, PartialEq)] From cbde9565eb0718858c3d32be38e8952fccda4097 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 14:31:16 +0100 Subject: [PATCH 20/25] rename cb_agent to container_builder_agent --- .../src/controller/build/resource/agent.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 00cc65c65..2de45253a 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -58,30 +58,36 @@ pub fn build_agent_deployment( agent_config: &ValidatedAgentConfig, ) -> Deployment { let resource_names = cluster.agent_resource_names(); - let mut cb_agent = new_container_builder(&AGENT_CONTAINER_NAME); + let mut container_builder_agent = new_container_builder(&AGENT_CONTAINER_NAME); let mut pod_builder = PodBuilder::new(); match &agent_config.connection { AgentConnection::Plaintext => {} AgentConnection::Tls { server_ca_secret_class, - } => { - add_kafka_tls_volume_and_mount(server_ca_secret_class, &mut pod_builder, &mut cb_agent) - } + } => add_kafka_tls_volume_and_mount( + server_ca_secret_class, + &mut pod_builder, + &mut container_builder_agent, + ), AgentConnection::MutualTls { server_ca_secret_class, client_credential, } => { - add_kafka_tls_volume_and_mount(server_ca_secret_class, &mut pod_builder, &mut cb_agent); + add_kafka_tls_volume_and_mount( + server_ca_secret_class, + &mut pod_builder, + &mut container_builder_agent, + ); client_credential - .add_volumes_and_mounts(&mut pod_builder, vec![&mut cb_agent]) + .add_volumes_and_mounts(&mut pod_builder, vec![&mut container_builder_agent]) .expect( "the agent Pod has no other volume or mount for the TLS client certificate", ); } } - cb_agent + container_builder_agent .image(&agent_config.image) .command(vec!["stackable-kafka-agent".to_owned()]) .args(vec!["run".to_owned()]) @@ -102,7 +108,7 @@ pub fn build_agent_deployment( .build(), ) .image_pull_secrets_from_product_image(&cluster.image) - .add_container(cb_agent.build()) + .add_container(container_builder_agent.build()) .service_account_name(resource_names.service_account_name().to_string()) .security_context( PodSecurityContextBuilder::with_stackable_defaults() From e5e54fd896921cc48e0275962dc06b2ee3d932aa Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 14:54:47 +0100 Subject: [PATCH 21/25] add deref tests for new constants --- .../src/controller/build/resource/agent.rs | 9 +++++++++ rust/shared/src/agent.rs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/rust/operator-binary/src/controller/build/resource/agent.rs b/rust/operator-binary/src/controller/build/resource/agent.rs index 2de45253a..966b62fff 100644 --- a/rust/operator-binary/src/controller/build/resource/agent.rs +++ b/rust/operator-binary/src/controller/build/resource/agent.rs @@ -294,6 +294,15 @@ mod tests { .expect("must be serializable") } + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *AGENT_CONTAINER_NAME; + let _ = *KAFKA_TLS_VOLUME_NAME; + let _ = *KUBERNETES_NODE_NAME; + let _ = *KUBERNETES_CLUSTER_DOMAIN; + } + #[test] fn agent_config_is_only_resolved_if_management_access_is_enabled() { assert!( diff --git a/rust/shared/src/agent.rs b/rust/shared/src/agent.rs index c50170e06..c481cbc47 100644 --- a/rust/shared/src/agent.rs +++ b/rust/shared/src/agent.rs @@ -31,6 +31,15 @@ mod tests { use super::*; + #[test] + fn test_constants() { + // Test that dereferencing the constants does not panic. + let _ = *ENV_CLUSTER_NAME; + let _ = *ENV_CLUSTER_NAMESPACE; + let _ = *ENV_CLIENT_SECURITY; + let _ = *ENV_BOOTSTRAP_SERVERS; + } + #[rstest] #[case::plaintext(ClientSecurity::Plaintext, "plaintext")] #[case::tls(ClientSecurity::Tls, "tls")] From 42d02bfe8fd19d7b4712ae8ca3cb7372431412cb Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Tue, 27 Oct 2026 18:52:16 +0100 Subject: [PATCH 22/25] regenerate-nix --- Cargo.nix | 20 ++++++++++---------- crate-hashes.json | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.nix b/Cargo.nix index 0529432e5..691a18e6b 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5456,7 +5456,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "k8s_version"; authors = [ @@ -10389,7 +10389,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_agent"; authors = [ @@ -10432,7 +10432,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_certs"; authors = [ @@ -10704,7 +10704,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_operator"; authors = [ @@ -10909,7 +10909,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10944,7 +10944,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_shared"; authors = [ @@ -11025,7 +11025,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_telemetry"; authors = [ @@ -11135,7 +11135,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_versioned"; authors = [ @@ -11181,7 +11181,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11245,7 +11245,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; - sha256 = "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm"; + sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_webhook"; authors = [ diff --git a/crate-hashes.json b/crate-hashes.json index 017105d5a..405952ac3 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,12 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0vdnhvfn85qnm5845mad24smhdp2y6nznlgagbp3g42pi042g9pm" + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s" } \ No newline at end of file From bdda9d08b1bdcf5b044f74c24ea119c182cfb3ac Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 28 Oct 2026 15:53:58 +0100 Subject: [PATCH 23/25] bump operator-rs --- Cargo.lock | 20 ++++++++++---------- Cargo.nix | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 288c23de1..e612f604b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.4" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "darling 0.24.1", "regex", @@ -3168,7 +3168,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-agent" version = "0.1.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "k8s-openapi", "schemars", @@ -3180,7 +3180,7 @@ dependencies = [ [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "const-oid", "ecdsa", @@ -3247,7 +3247,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.121.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "base64 0.23.1", "clap", @@ -3292,7 +3292,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3303,7 +3303,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.2.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "jiff", "k8s-openapi", @@ -3320,7 +3320,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "axum", "clap", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "kube", "schemars", @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "convert_case", "darling 0.24.1", @@ -3374,7 +3374,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#ccfff5810f9b5affae4d144b3cf04ca88677e23e" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 691a18e6b..4cc6452f5 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5455,7 +5455,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "k8s_version"; @@ -10388,7 +10388,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_agent"; @@ -10431,7 +10431,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_certs"; @@ -10703,7 +10703,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_operator"; @@ -10908,7 +10908,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; procMacro = true; @@ -10943,7 +10943,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_shared"; @@ -11024,7 +11024,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_telemetry"; @@ -11134,7 +11134,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_versioned"; @@ -11180,7 +11180,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; procMacro = true; @@ -11244,7 +11244,7 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "ccfff5810f9b5affae4d144b3cf04ca88677e23e"; + rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; }; libName = "stackable_webhook"; From a89b5db6d7d678b1ae09c3446c1e268469e0a1f2 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 28 Oct 2026 17:07:16 +0100 Subject: [PATCH 24/25] regenerate nix --- Cargo.nix | 20 ++++++++++---------- crate-hashes.json | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.nix b/Cargo.nix index 4cc6452f5..b67bd259a 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5456,7 +5456,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "k8s_version"; authors = [ @@ -10389,7 +10389,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_agent"; authors = [ @@ -10432,7 +10432,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_certs"; authors = [ @@ -10704,7 +10704,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_operator"; authors = [ @@ -10909,7 +10909,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10944,7 +10944,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_shared"; authors = [ @@ -11025,7 +11025,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_telemetry"; authors = [ @@ -11135,7 +11135,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_versioned"; authors = [ @@ -11181,7 +11181,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11245,7 +11245,7 @@ rec { src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s"; + sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; }; libName = "stackable_webhook"; authors = [ diff --git a/crate-hashes.json b/crate-hashes.json index 405952ac3..fd83bfb02 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,12 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "052r8sbdgl89fy4jrkl1jjzjp5fj731pips5a95jd5hm51ymwi4s" + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715" } \ No newline at end of file From 43657d4c2b69e4679ed4133afd4ad7d48bdc6bf5 Mon Sep 17 00:00:00 2001 From: Benedikt Labrenz Date: Wed, 28 Oct 2026 17:10:54 +0100 Subject: [PATCH 25/25] regenerate nix --- Cargo.lock | 20 ++++++++++---------- Cargo.nix | 40 ++++++++++++++++++++-------------------- crate-hashes.json | 20 ++++++++++---------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e612f604b..ac2068d2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.4" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "darling 0.24.1", "regex", @@ -3168,7 +3168,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-agent" version = "0.1.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "k8s-openapi", "schemars", @@ -3180,7 +3180,7 @@ dependencies = [ [[package]] name = "stackable-certs" version = "0.4.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "const-oid", "ecdsa", @@ -3247,7 +3247,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.121.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "base64 0.23.1", "clap", @@ -3292,7 +3292,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "darling 0.24.1", "proc-macro2", @@ -3303,7 +3303,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.2.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "jiff", "k8s-openapi", @@ -3320,7 +3320,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.5" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "axum", "clap", @@ -3344,7 +3344,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "kube", "schemars", @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.13.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "convert_case", "darling 0.24.1", @@ -3374,7 +3374,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.10.0" -source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#63760c6a00a9b6c0fa564201c2b442307b5e7069" +source = "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#b61f619aa15efa2fa8c88d7eeae6154c3fb3918a" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index b67bd259a..18130a181 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -5455,8 +5455,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "k8s_version"; authors = [ @@ -10388,8 +10388,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_agent"; authors = [ @@ -10431,8 +10431,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_certs"; authors = [ @@ -10703,8 +10703,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_operator"; authors = [ @@ -10908,8 +10908,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -10943,8 +10943,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_shared"; authors = [ @@ -11024,8 +11024,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_telemetry"; authors = [ @@ -11134,8 +11134,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_versioned"; authors = [ @@ -11180,8 +11180,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -11244,8 +11244,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech/operator-rs.git"; - rev = "63760c6a00a9b6c0fa564201c2b442307b5e7069"; - sha256 = "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715"; + rev = "b61f619aa15efa2fa8c88d7eeae6154c3fb3918a"; + sha256 = "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq"; }; libName = "stackable_webhook"; authors = [ diff --git a/crate-hashes.json b/crate-hashes.json index fd83bfb02..f2a7eec62 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,12 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715", - "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "1962ivywrqyzjxa29w6i6gkhblaqd74q3wqwprrggh85z8kfg715" + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#k8s-version@0.1.4": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-agent@0.1.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-certs@0.4.1": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator-derive@0.3.1": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-operator@0.121.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-shared@0.2.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-telemetry@0.6.5": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned-macros@0.13.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-versioned@0.13.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq", + "git+https://github.com/stackabletech/operator-rs.git?branch=feat%2Fplatform-access#stackable-webhook@0.10.0": "0ivrv56a8yzy68d9hr7cvy7hk5w0i2hidzlnns23h0g60ynb3axq" } \ No newline at end of file