2323 ModelReference ,
2424)
2525from fixlib .config import Config
26- from fixlib .core .actions import CoreFeedback
26+ from fixlib .core .actions import CoreFeedback , ErrorAccumulator
2727from fixlib .graph import Graph , EdgeKey
2828from fixlib .json import from_json as from_js , value_in_path
2929from fixlib .json_bender import bend , Bender , S , Bend , MapDict , F
@@ -78,6 +78,7 @@ def __init__(
7878 credentials : GoogleAuthCredentials ,
7979 executor : ExecutorQueue ,
8080 core_feedback : CoreFeedback ,
81+ error_accumulator : ErrorAccumulator ,
8182 fallback_global_region : GcpRegion ,
8283 region : Optional [GcpRegion ] = None ,
8384 graph_nodes_access : Optional [Lock ] = None ,
@@ -87,12 +88,11 @@ def __init__(
8788 self .cloud = cloud
8889 self .region = region
8990 self .project = project
90- self .client = GcpClient (
91- credentials , project_id = project .id , region = region .name if region else None , core_feedback = core_feedback
92- )
91+ self .client = GcpClient (credentials , project_id = project .id , region = region .name if region else None )
9392 self .executor = executor
9493 self .name = f"GCP:{ project .name } "
9594 self .core_feedback = core_feedback
95+ self .error_accumulator = error_accumulator
9696 self .fallback_global_region = fallback_global_region
9797 self .region_by_name : Dict [str , GcpRegion ] = {}
9898 self .region_by_zone_name : Dict [str , GcpRegion ] = {}
@@ -272,6 +272,7 @@ def for_region(self, region: GcpRegion) -> GraphBuilder:
272272 self .client .credentials ,
273273 self .executor ,
274274 self .core_feedback ,
275+ self .error_accumulator ,
275276 self .fallback_global_region ,
276277 region ,
277278 self .graph_nodes_access ,
@@ -381,7 +382,14 @@ def collect_resources(cls: Type[GcpResource], builder: GraphBuilder, **kwargs: A
381382 log .info (f"[GCP:{ builder .project .id } ] Collecting { cls .kind } " )
382383 if spec := cls .api_spec :
383384 expected_errors = GcpExpectedErrorCodes | (spec .expected_errors or set ())
384- with GcpErrorHandler (builder .core_feedback , expected_errors , f" in { builder .project .id } kind { cls .kind } " ):
385+ with GcpErrorHandler (
386+ spec .action ,
387+ builder .error_accumulator ,
388+ spec .service ,
389+ builder .region .safe_name if builder .region else None ,
390+ expected_errors ,
391+ f" in { builder .project .id } kind { cls .kind } " ,
392+ ):
385393 items = builder .client .list (spec , ** kwargs )
386394 resources = cls .collect (items , builder )
387395 log .info (f"[GCP:{ builder .project .id } ] finished collecting: { cls .kind } " )
@@ -610,12 +618,18 @@ class GcpZone(GcpResource, BaseZone):
610618class GcpErrorHandler :
611619 def __init__ (
612620 self ,
613- core_feedback : CoreFeedback ,
621+ action : str ,
622+ error_accumulator : ErrorAccumulator ,
623+ service : str ,
624+ region : Optional [str ],
614625 expected_errors : Set [str ],
615626 extra_info : str = "" ,
616627 expected_message_substrings : Optional [Set [str ]] = None ,
617628 ) -> None :
618- self .core_feedback = core_feedback
629+ self .action = action
630+ self .error_accumulator = error_accumulator
631+ self .service = service
632+ self .region = region
619633 self .extra_info = extra_info
620634 self .expected_errors = expected_errors
621635 self .expected_message_substrings = expected_message_substrings
@@ -649,31 +663,39 @@ def __exit__(
649663 if self .expected_message_substrings :
650664 for substring in self .expected_message_substrings :
651665 if substring in error_details :
652- log .info (f"Ignoring expected HttpError in { self .extra_info } : { error_details } ." )
653666 return True # Suppress the exception
654667 except Exception as ex :
655668 errors = {f"ParseError:unknown:{ ex } " }
656669 error_summary = " Error Codes: " + (", " .join (errors )) if errors else ""
657670
658671 if errors and errors .issubset (self .expected_errors ):
659- log .info (
672+ log .debug (
660673 f"Expected Exception while collecting{ self .extra_info } ({ exc_type .__name__ } ): "
661674 f"{ error_details } { error_summary } . Ignore."
662675 )
663676 return True
664677
665678 if not Config .gcp .discard_account_on_resource_error :
666- self .core_feedback .error (
667- f"Error while collecting{ self .extra_info } ({ exc_type .__name__ } ): " f"{ error_details } { error_summary } " ,
668- log ,
679+ if exc_type is HttpError and isinstance (exc_value , HttpError ):
680+ if exc_value .resp .status == 403 :
681+ self .error_accumulator .add_error (
682+ as_info = False ,
683+ error_kind = "AccessDenied" ,
684+ service = self .service ,
685+ action = self .action ,
686+ message = f"Access denied: { error_details } " ,
687+ region = None ,
688+ )
689+ return True
690+
691+ self .error_accumulator .add_error (
692+ as_info = False ,
693+ error_kind = exc_type .__name__ ,
694+ service = self .service ,
695+ action = self .action ,
696+ message = f"Error while collecting{ self .extra_info } : { error_details } { error_summary } " ,
697+ region = self .region ,
669698 )
670699 return True
671700
672- if exc_type is HttpError and isinstance (exc_value , HttpError ):
673- if exc_value .resp .status == 403 :
674- self .core_feedback .error (
675- f"Access denied{ self .extra_info } : { error_details } Error Codes: { error_summary } " , log
676- )
677- return True
678-
679701 return False
0 commit comments