Skip to content

Commit

Permalink
[feat] Provide one summary for all kinds
Browse files Browse the repository at this point in the history
  • Loading branch information
aquamatthias committed Sep 25, 2024
1 parent 8e49b7d commit 6d23f40
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 37 deletions.
17 changes: 6 additions & 11 deletions fixbackend/inventory/inventory_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
SearchTableRequest,
TimeseriesRequest,
Scatters,
KindUsage,
)
from fixbackend.streaming_response import streaming_response, StreamOnSuccessResponse
from fixbackend.workspaces.dependencies import UserWorkspaceDependency
Expand Down Expand Up @@ -167,6 +168,7 @@ async def summary(graph_db: CurrentGraphDbDependency, workspace: UserWorkspaceDe
async def model(
graph_db: CurrentGraphDbDependency,
kind: Optional[List[str]] = Query(default=None, description="Kinds to return."),
kind_filter: Optional[List[str]] = Query(default=None, description="Kind filter to apply."),
with_bases: bool = Query(default=False, description="Include base kinds."),
with_property_kinds: bool = Query(default=False, description="Include property kinds."),
aggregate_roots_only: bool = Query(default=True, description="Include only aggregate roots."),
Expand All @@ -179,6 +181,7 @@ async def model(
graph_db,
result_format="simple",
kind=kind,
kind_filter=kind_filter,
with_bases=with_bases,
with_property_kinds=with_property_kinds,
aggregate_roots_only=aggregate_roots_only,
Expand Down Expand Up @@ -410,16 +413,8 @@ async def timeseries(graph_db: CurrentGraphDbDependency, ts: TimeseriesRequest)
aggregation=ts.aggregation,
)

@router.get("/descendant/summary/{level}", tags=["timeseries"])
async def descendant_summary_account(
graph_db: CurrentGraphDbDependency, level: Literal["account", "region", "zone"]
) -> Dict[str, Dict[str, int]]:
return await inventory().descendant_summary(graph_db, level)

@router.get("/descendant/count/{level}", tags=["timeseries"])
async def descendant_count_account(
graph_db: CurrentGraphDbDependency, level: Literal["account", "region", "zone"]
) -> Dict[str, int]:
return await inventory().descendant_count_by(graph_db, level)
@router.get("/descendant/summary", tags=["search"])
async def descendant_summary_account(graph_db: CurrentGraphDbDependency) -> Dict[str, KindUsage]:
return await inventory().descendant_summary(graph_db)

return router
6 changes: 6 additions & 0 deletions fixbackend/inventory/inventory_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,9 @@ class TimeseriesRequest(BaseModel):
group: Optional[Set[str]] = None
filter_group: Optional[List[str]] = None
aggregation: Optional[str] = None


class KindUsage(BaseModel):
accounts: int = Field(default=0, description="The number of accounts using this kind.")
regions: int = Field(default=0, description="The number of regions using this kind.")
resources: int = Field(default=0, description="The number of resources of this kind.")
47 changes: 21 additions & 26 deletions fixbackend/inventory/inventory_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
Scatter,
Scatters,
SearchTableRequest,
KindUsage,
)
from fixbackend.logging_context import set_cloud_account_id, set_fix_cloud_account_id, set_workspace_id
from fixbackend.types import Redis
Expand Down Expand Up @@ -860,35 +861,29 @@ async def overall_score() -> Tuple[int, int]:

return await self.cache.call(compute_inventory_info, key=str(dba.workspace_id))(duration)

async def descendant_summary(
self, dba: GraphDatabaseAccess, kind: Literal["account", "region", "zone"]
) -> Dict[str, Dict[str, int]]:
async def descendant_summary(self, dba: GraphDatabaseAccess) -> Dict[str, KindUsage]:

async def compute_descendant_summary(on: str) -> Dict[str, Dict[str, int]]:
result: Dict[str, Dict[str, int]] = defaultdict(lambda: defaultdict(int))
async with self.client.search(dba, f"is({on}) and /metadata.descendant_count>0") as response:
async def compute_descendant_summary() -> Dict[str, KindUsage]:
account_usage: Dict[str, Dict[str, int]] = defaultdict(lambda: defaultdict(int))
region_usage: Dict[str, Dict[str, int]] = defaultdict(lambda: defaultdict(int))
async with self.client.search(dba, f"is(account) and /metadata.descendant_count>0") as response:
async for acc in response:
if level_name := value_in_path(acc, "reported.id"):
if account_id := value_in_path(acc, "reported.id"):
descendant_summary = value_in_path(acc, "metadata.descendant_summary") or {}
for descendant_kind, count in descendant_summary.items():
result[level_name][descendant_kind] += count
return result

return await self.cache.call(compute_descendant_summary, key=str(dba.workspace_id))(kind)

async def descendant_count_by(
self, dba: GraphDatabaseAccess, kind: Literal["account", "region", "zone"]
) -> Dict[str, int]:

async def compute_descendant_count_by(on: str) -> Dict[str, int]:
counter: Dict[str, Dict[str, int]] = defaultdict(lambda: defaultdict(int))
async with self.client.search(dba, f"is({on}) and /metadata.descendant_count>0") as response:
account_usage[descendant_kind][account_id] += count
async with self.client.search(dba, f"is(region) and /metadata.descendant_count>0") as response:
async for acc in response:
if level_name := value_in_path(acc, "reported.id"):
if region_id := value_in_path(acc, "reported.id"):
descendant_summary = value_in_path(acc, "metadata.descendant_summary") or {}
for descendant_kind in descendant_summary:
counter[descendant_kind][level_name] = 1

return {k: len(v) for k, v in counter.items()}

return await self.cache.call(compute_descendant_count_by, key=str(dba.workspace_id))(kind)
for descendant_kind, count in descendant_summary.items():
region_usage[descendant_kind][region_id] += count
kind_usage: Dict[str, KindUsage] = defaultdict(lambda: KindUsage())

Check warning on line 881 in fixbackend/inventory/inventory_service.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

fixbackend/inventory/inventory_service.py#L881

Lambda may not be necessary
for kind, accounts in account_usage.items():
kind_usage[kind].accounts = len(accounts)
kind_usage[kind].resources = sum(accounts.values())
for kind, regions in region_usage.items():
kind_usage[kind].regions = len(regions)
return kind_usage

return await self.cache.call(compute_descendant_summary, key=str(dba.workspace_id))()

0 comments on commit 6d23f40

Please sign in to comment.