@@ -38,8 +38,9 @@ use stackable_operator::{
3838 api:: {
3939 apps:: v1:: { DaemonSet , DaemonSetSpec } ,
4040 core:: v1:: {
41- ConfigMap , EmptyDirVolumeSource , EnvVar , HTTPGetAction , Probe , SecretVolumeSource ,
42- Service , ServiceAccount , ServicePort , ServiceSpec ,
41+ ConfigMap , EmptyDirVolumeSource , EnvVar , EnvVarSource , HTTPGetAction ,
42+ ObjectFieldSelector , Probe , SecretVolumeSource , Service , ServiceAccount ,
43+ ServicePort , ServiceSpec ,
4344 } ,
4445 } ,
4546 apimachinery:: pkg:: { apis:: meta:: v1:: LabelSelector , util:: intstr:: IntOrString } ,
@@ -69,7 +70,7 @@ use stackable_operator::{
6970 operations:: ClusterOperationsConditionBuilder ,
7071 } ,
7172 time:: Duration ,
72- utils:: COMMON_BASH_TRAP_FUNCTIONS ,
73+ utils:: { COMMON_BASH_TRAP_FUNCTIONS , cluster_info :: KubernetesClusterInfo } ,
7374} ;
7475use strum:: { EnumDiscriminants , IntoStaticStr } ;
7576
@@ -144,6 +145,7 @@ pub struct Ctx {
144145 pub product_config : ProductConfigManager ,
145146 pub opa_bundle_builder_image : String ,
146147 pub user_info_fetcher_image : String ,
148+ pub cluster_info : KubernetesClusterInfo ,
147149}
148150
149151#[ derive( Snafu , Debug , EnumDiscriminants ) ]
@@ -492,6 +494,7 @@ pub async fn reconcile_opa(
492494 & ctx. opa_bundle_builder_image ,
493495 & ctx. user_info_fetcher_image ,
494496 & rbac_sa,
497+ & ctx. cluster_info ,
495498 ) ?;
496499
497500 cluster_resources
@@ -714,6 +717,44 @@ fn build_server_rolegroup_config_map(
714717 } )
715718}
716719
720+ /// Env variables that are need to run stackable Rust binaries, such as
721+ /// * opa-bundle-builder
722+ /// * user-info-fetcher
723+ fn add_stackable_rust_cli_env_vars (
724+ container_builder : & mut ContainerBuilder ,
725+ cluster_info : & KubernetesClusterInfo ,
726+ log_level : impl Into < String > ,
727+ container : & v1alpha1:: Container ,
728+ ) {
729+ let log_level = log_level. into ( ) ;
730+ container_builder
731+ . add_env_var ( "CONSOLE_LOG_LEVEL" , log_level. clone ( ) )
732+ . add_env_var ( "FILE_LOG_LEVEL" , log_level)
733+ . add_env_var (
734+ "FILE_LOG_DIRECTORY" ,
735+ format ! ( "{STACKABLE_LOG_DIR}/{container}" , ) ,
736+ )
737+ . add_env_var_from_source (
738+ "KUBERNETES_NODE_NAME" ,
739+ EnvVarSource {
740+ field_ref : Some ( ObjectFieldSelector {
741+ field_path : "spec.nodeName" . to_owned ( ) ,
742+ ..Default :: default ( )
743+ } ) ,
744+ ..Default :: default ( )
745+ } ,
746+ )
747+ // We set the cluster domain always explicitly, because the product Pods does not have the
748+ // RBAC permission to get the `nodes/proxy` resource at cluster scope. This is likely
749+ // because it only has a RoleBinding and no ClusterRoleBinding.
750+ // By setting the cluster domain explicitly we avoid that the sidecars try to look it up
751+ // based on some information coming from the node.
752+ . add_env_var (
753+ "KUBERNETES_CLUSTER_DOMAIN" ,
754+ cluster_info. cluster_domain . to_string ( ) ,
755+ ) ;
756+ }
757+
717758/// The rolegroup [`DaemonSet`] runs the rolegroup, as configured by the administrator.
718759///
719760/// The [`Pod`](`stackable_operator::k8s_openapi::api::core::v1::Pod`)s are accessible through the
@@ -732,6 +773,7 @@ fn build_server_rolegroup_daemonset(
732773 opa_bundle_builder_image : & str ,
733774 user_info_fetcher_image : & str ,
734775 service_account : & ServiceAccount ,
776+ cluster_info : & KubernetesClusterInfo ,
735777) -> Result < DaemonSet > {
736778 let opa_name = opa. metadata . name . as_deref ( ) . context ( NoNameSnafu ) ?;
737779 let role = opa. role ( opa_role) ;
@@ -782,8 +824,6 @@ fn build_server_rolegroup_daemonset(
782824 . context ( AddVolumeMountSnafu ) ?
783825 . resources ( merged_config. resources . to_owned ( ) . into ( ) ) ;
784826
785- let console_and_file_log_level = bundle_builder_log_level ( merged_config) ;
786-
787827 cb_bundle_builder
788828 . image_from_product_image ( resolved_product_image) // inherit the pull policy and pull secrets, and then...
789829 . image ( opa_bundle_builder_image) // ...override the image
@@ -799,12 +839,6 @@ fn build_server_rolegroup_daemonset(
799839 & bundle_builder_container_name,
800840 ) ] )
801841 . add_env_var_from_field_path ( "WATCH_NAMESPACE" , FieldPathEnvVar :: Namespace )
802- . add_env_var ( "CONSOLE_LOG_LEVEL" , console_and_file_log_level. to_string ( ) )
803- . add_env_var ( "FILE_LOG_LEVEL" , console_and_file_log_level. to_string ( ) )
804- . add_env_var (
805- "FILE_LOG_DIRECTORY" ,
806- format ! ( "{STACKABLE_LOG_DIR}/{bundle_builder_container_name}" ) ,
807- )
808842 . add_volume_mount ( BUNDLES_VOLUME_NAME , BUNDLES_DIR )
809843 . context ( AddVolumeMountSnafu ) ?
810844 . add_volume_mount ( LOG_VOLUME_NAME , STACKABLE_LOG_DIR )
@@ -838,6 +872,12 @@ fn build_server_rolegroup_daemonset(
838872 } ) ,
839873 ..Probe :: default ( )
840874 } ) ;
875+ add_stackable_rust_cli_env_vars (
876+ & mut cb_bundle_builder,
877+ cluster_info,
878+ sidecar_container_log_level ( merged_config, & v1alpha1:: Container :: BundleBuilder ) . to_string ( ) ,
879+ & v1alpha1:: Container :: BundleBuilder ,
880+ ) ;
841881
842882 cb_opa
843883 . image_from_product_image ( resolved_product_image)
@@ -949,6 +989,13 @@ fn build_server_rolegroup_daemonset(
949989 . with_memory_limit ( "128Mi" )
950990 . build ( ) ,
951991 ) ;
992+ add_stackable_rust_cli_env_vars (
993+ & mut cb_user_info_fetcher,
994+ cluster_info,
995+ sidecar_container_log_level ( merged_config, & v1alpha1:: Container :: UserInfoFetcher )
996+ . to_string ( ) ,
997+ & v1alpha1:: Container :: UserInfoFetcher ,
998+ ) ;
952999
9531000 match & user_info. backend {
9541001 user_info_fetcher:: v1alpha1:: Backend :: None { } => { }
@@ -1257,13 +1304,42 @@ fn build_bundle_builder_start_command(
12571304 }
12581305}
12591306
1260- fn bundle_builder_log_level ( merged_config : & v1alpha1:: OpaConfig ) -> BundleBuilderLogLevel {
1307+ /// TODO: *Technically* this function would need to be way more complex.
1308+ /// For now it's a good-enough approximation, this is fine :D
1309+ ///
1310+ /// The following config
1311+ ///
1312+ /// ```
1313+ /// containers:
1314+ /// opa-bundle-builder:
1315+ /// console:
1316+ /// level: DEBUG
1317+ /// file:
1318+ /// level: INFO
1319+ /// loggers:
1320+ /// ROOT:
1321+ /// level: INFO
1322+ /// my.module:
1323+ /// level: DEBUG
1324+ /// some.chatty.module:
1325+ /// level: NONE
1326+ /// ```
1327+ ///
1328+ /// should result in
1329+ /// `CONSOLE_LOG_LEVEL=info,my.module=debug,some.chatty.module=none`
1330+ /// and
1331+ /// `FILE_LOG_LEVEL=info,my.module=info,some.chatty.module=none`.
1332+ /// Note that `my.module` is `info` instead of `debug`, because it's clamped by the global file log
1333+ /// level.
1334+ ///
1335+ /// Context: https://docs.stackable.tech/home/stable/concepts/logging/
1336+ fn sidecar_container_log_level (
1337+ merged_config : & v1alpha1:: OpaConfig ,
1338+ sidecar_container : & v1alpha1:: Container ,
1339+ ) -> BundleBuilderLogLevel {
12611340 if let Some ( ContainerLogConfig {
12621341 choice : Some ( ContainerLogConfigChoice :: Automatic ( log_config) ) ,
1263- } ) = merged_config
1264- . logging
1265- . containers
1266- . get ( & v1alpha1:: Container :: BundleBuilder )
1342+ } ) = merged_config. logging . containers . get ( sidecar_container)
12671343 {
12681344 if let Some ( logger) = log_config
12691345 . loggers
0 commit comments