Coverage for src/fastapi_cloud_cli/commands/integrations/resources/list.py: 100%
50 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +0000
1from typing import Annotated, Any 1abcdefg
3import typer 1abcdefg
4from pydantic import AliasPath, BaseModel, Field 1abcdefg
5from rich.table import Table 1abcdefg
6from rich.text import Text 1abcdefg
7from rich_toolkit import RichToolkit 1abcdefg
9from fastapi_cloud_cli.api import APIClient 1abcdefg
10from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context 1abcdefg
11from fastapi_cloud_cli.commands.integrations.resources._app import resources_app 1abcdefg
12from fastapi_cloud_cli.commands.integrations.resources.providers import ( 1abcdefg
13 PROVIDER_NAMES,
14 Provider,
15)
16from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail 1abcdefg
17from fastapi_cloud_cli.utils.execution import JsonOutputOption 1abcdefg
20class ConnectedResource(BaseModel): 1abcdefg
21 id: str 1abcdefg
22 name: str 1abcdefg
23 provider: Provider = Field(validation_alias=AliasPath("provider_metadata", "type")) 1abcdefg
26class ConnectedResourcesListAPIResponse(BaseModel): 1abcdefg
27 data: list[ConnectedResource] 1abcdefg
30class ResourcesListOutput(BaseModel): 1abcdefg
31 app_id: str 1abcdefg
32 resources: list[ConnectedResource] 1abcdefg
35def _get_resources(client: APIClient, *, app_id: str) -> list[ConnectedResource]: 1abcdefg
36 response = client.get(f"/apps/{app_id}/connected-resources") 1QRvhoJwSTziqLAUVBmrMCWXDjsNEYZxkpKy01FntOG23HluPI
37 response.raise_for_status() 1QRvhoJwSTziqLAUVBmrMCWXDjsNEYZxkpKy01FntOG23HluPI
39 return ConnectedResourcesListAPIResponse.model_validate(response.json()).data 1QRvhowSTziqAUVBmrCWXDjsEYZxkpy01FntG23HluI
42def _get_resources_table(resources: list[ConnectedResource]) -> Table: 1abcdefg
43 table = Table.grid(padding=(0, 2), pad_edge=False) 1himjknl
44 table.add_column("Name", no_wrap=True) 1himjknl
45 table.add_column("Provider", no_wrap=True) 1himjknl
46 table.add_column("Resource ID", no_wrap=True, overflow="ignore") 1himjknl
47 table.add_row( 1himjknl
48 Text("Name", style="bold"),
49 Text("Provider", style="bold"),
50 Text("Resource ID", style="bold"),
51 )
52 table.add_row("", "", "") 1himjknl
54 for resource in resources: 1himjknl
55 table.add_row( 1himjknl
56 Text(resource.name),
57 Text(PROVIDER_NAMES[resource.provider], style="dim"),
58 Text(resource.id),
59 )
61 return table 1himjknl
64def _render_resources_list_output( 1abicdjefgl
65 data: ResourcesListOutput,
66 toolkit: RichToolkit,
67) -> None:
68 toolkit.print_title("connected resources") 1hoiqmrjskpntlu
69 toolkit.print_line() 1hoiqmrjskpntlu
71 if not data.resources: 1hoiqmrjskpntlu
72 toolkit.print("No connected resources found.", bullet=False) 1oqrsptu
73 return 1oqrsptu
75 toolkit.print(_get_resources_table(data.resources), bullet=False) 1himjknl
78@resources_app.command("list", cls=UserCommand) 1abcdefg
79def list_resources( 1ab#cd$efg%
80 ctx: typer.Context,
81 app_id: Annotated[
82 str | None,
83 typer.Option(
84 "--app-id",
85 help="ID of the app whose connected resources should be listed.",
86 ),
87 ] = None,
88 json_output: JsonOutputOption = False,
89) -> Any:
90 """
91 List resources connected to an app.
92 """
94 toolkit = get_user_command_context(ctx).toolkit 1vho4Jwziq5LABmr6MCDjs7NExkp8KyFnt9OGHlu!PI
96 app_id = resolve_app_id_or_fail(toolkit, app_id=app_id) 1vho4Jwziq5LABmr6MCDjs7NExkp8KyFnt9OGHlu!PI
98 with APIClient() as client: 1vhoJwziqLABmrMCDjsNExkpKyFntOGHluPI
99 with ( 1vhoJwxkpKy
100 toolkit.progress(
101 title="Fetching connected resources",
102 transient=True,
103 ) as progress,
104 client.handle_http_errors(
105 progress,
106 default_message=(
107 "Error fetching connected resources. Please try again later."
108 ),
109 not_found_message="App not found.",
110 toolkit=toolkit,
111 ),
112 ):
113 resources = _get_resources(client, app_id=app_id) 1vhoJwziqLABmrMCDjsNExkpKyFntOGHluPI
115 toolkit.success( 1vhowziqABmrCDjsExkpyFntGHluI
116 ResourcesListOutput(app_id=app_id, resources=resources),
117 render_output=_render_resources_list_output,
118 )