@@ -23,7 +23,9 @@ use std::time::Duration;
2323use tokio:: sync:: mpsc;
2424use tokio:: task:: JoinHandle ;
2525
26- use crate :: kube:: api:: { get_flux_api_resources_with_fallback, is_version_missing_error} ;
26+ use crate :: kube:: api:: {
27+ get_flux_api_resources_with_fallback, is_forbidden_error, is_version_missing_error,
28+ } ;
2729use crate :: models:: FluxResourceKind ;
2830
2931/// Maximum interval between watch-reconnect attempts.
@@ -217,7 +219,8 @@ impl ResourceWatcher {
217219 let ev = match event {
218220 Ok ( ev) => ev,
219221 Err ( e) => {
220- if is_version_missing_error ( & format ! ( "{}" , e) ) {
222+ let err_str = format ! ( "{}" , e) ;
223+ if is_version_missing_error ( & err_str) {
221224 // CRD not installed or version not served — stop, don't retry.
222225 // Clear any degraded state: this watcher is intentionally
223226 // stopping, not reconnecting.
@@ -236,6 +239,26 @@ impl ResourceWatcher {
236239 break ;
237240 }
238241
242+ if is_forbidden_error ( & err_str) {
243+ // RBAC denies access to this resource — retrying won't help
244+ // within the session, so stop rather than flag the watch
245+ // as degraded. Clear any degraded state from earlier errors.
246+ if error_count > 0 {
247+ let _ = event_tx
248+ . send ( WatchEvent :: WatcherRecovered ( display_name. clone ( ) ) ) ;
249+ }
250+ tracing:: info!(
251+ "{} watch forbidden by RBAC, stopping watcher: {}" ,
252+ display_name,
253+ e
254+ ) ;
255+ let _ = event_tx. send ( WatchEvent :: Error ( format ! (
256+ "{} watch forbidden by RBAC: {}" ,
257+ display_name, e
258+ ) ) ) ;
259+ break ;
260+ }
261+
239262 error_count += 1 ;
240263 if error_count == 1 {
241264 // First error after healthy operation: flag as degraded
@@ -331,6 +354,16 @@ impl ResourceWatcher {
331354 let ev = match event {
332355 Ok ( ev) => ev,
333356 Err ( e) => {
357+ if is_forbidden_error ( & format ! ( "{}" , e) ) {
358+ // RBAC denies access — retrying won't help, so stop rather
359+ // than flag the watch as degraded. Clear earlier degraded state.
360+ if error_count > 0 {
361+ let _ = event_tx
362+ . send ( WatchEvent :: WatcherRecovered ( WATCHER_NAME . to_string ( ) ) ) ;
363+ }
364+ tracing:: info!( "Pod watcher forbidden by RBAC, stopping: {}" , e) ;
365+ break ;
366+ }
334367 error_count += 1 ;
335368 if error_count == 1 {
336369 let _ = event_tx
@@ -394,6 +427,16 @@ impl ResourceWatcher {
394427 let ev = match event {
395428 Ok ( ev) => ev,
396429 Err ( e) => {
430+ if is_forbidden_error ( & format ! ( "{}" , e) ) {
431+ // RBAC denies access — retrying won't help, so stop rather
432+ // than flag the watch as degraded. Clear earlier degraded state.
433+ if error_count > 0 {
434+ let _ = event_tx
435+ . send ( WatchEvent :: WatcherRecovered ( WATCHER_NAME . to_string ( ) ) ) ;
436+ }
437+ tracing:: info!( "Deployment watcher forbidden by RBAC, stopping: {}" , e) ;
438+ break ;
439+ }
397440 error_count += 1 ;
398441 if error_count == 1 {
399442 let _ = event_tx
@@ -490,7 +533,8 @@ impl ResourceWatcher {
490533 let ev = match w. next ( ) . await {
491534 Some ( Ok ( ev) ) => ev,
492535 Some ( Err ( e) ) => {
493- if is_version_missing_error ( & format ! ( "{}" , e) ) && !version_working {
536+ let err_str = format ! ( "{}" , e) ;
537+ if is_version_missing_error ( & err_str) && !version_working {
494538 tracing:: debug!(
495539 "{} version {} not available, trying next version" ,
496540 display_name,
@@ -499,6 +543,26 @@ impl ResourceWatcher {
499543 break ; // Try next version
500544 }
501545
546+ if is_forbidden_error ( & err_str) {
547+ // RBAC denies access to this resource — every version
548+ // would be forbidden too, so stop rather than flag the
549+ // watch as degraded. Clear any degraded state first.
550+ if degraded_sent {
551+ let _ = event_tx
552+ . send ( WatchEvent :: WatcherRecovered ( resource_type. clone ( ) ) ) ;
553+ }
554+ tracing:: info!(
555+ "{} watch forbidden by RBAC, stopping watcher: {}" ,
556+ display_name,
557+ e
558+ ) ;
559+ let _ = event_tx. send ( WatchEvent :: Error ( format ! (
560+ "{} watch forbidden by RBAC: {}" ,
561+ display_name, e
562+ ) ) ) ;
563+ return ;
564+ }
565+
502566 error_count += 1 ;
503567 if !degraded_sent {
504568 degraded_sent = true ;
0 commit comments