Coverage for src/fastapi_cloud_cli/commands/tokens/list.py: 100%
51 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 BaseModel 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.tokens._app import tokens_app 1abcdefg
12from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail 1abcdefg
13from fastapi_cloud_cli.utils.execution import JsonOutputOption 1abcdefg
16class DeployToken(BaseModel): 1abcdefg
17 id: str 1abcdefg
18 name: str 1abcdefg
19 created_at: str 1abcdefg
20 expired_at: str 1abcdefg
23class DeployTokensListAPIResponse(BaseModel): 1abcdefg
24 data: list[DeployToken] 1abcdefg
27class DeployTokensListOutput(BaseModel): 1abcdefg
28 app_id: str 1abcdefg
29 tokens: list[DeployToken] 1abcdefg
32def _get_deploy_tokens(client: APIClient, app_id: str) -> DeployTokensListAPIResponse: 1abcdefg
33 response = client.get(f"/apps/{app_id}/tokens") 1vwhrxyiozAjsBCkpDEltFGmuHInq
34 response.raise_for_status() 1vwhrxyiozAjsBCkpDEltFGmuHInq
36 return DeployTokensListAPIResponse.model_validate(response.json()) 1vwhrxyiozAjsBCkpDEltFGmuHInq
39def _get_deploy_tokens_table(tokens: list[DeployToken]) -> Table: 1abcdefg
40 table = Table.grid(padding=(0, 2), pad_edge=False) 1hijklmn
41 table.add_column("Name", no_wrap=True) 1hijklmn
42 table.add_column("Expiration", no_wrap=True) 1hijklmn
43 table.add_column("ID", no_wrap=True, overflow="ignore") 1hijklmn
44 table.add_row( 1hijklmn
45 Text("Name", style="bold"),
46 Text("Expiration", style="bold"),
47 Text("ID", style="bold"),
48 )
49 table.add_row("", "", "") 1hijklmn
51 for token in tokens: 1hijklmn
52 table.add_row( 1hijklmn
53 Text(token.name),
54 Text(token.expired_at[:10], style="dim"),
55 Text(token.id),
56 )
58 return table 1hijklmn
61def _render_deploy_tokens_list_output( 1abocdpefgq
62 data: DeployTokensListOutput, toolkit: RichToolkit
63) -> None:
64 toolkit.print_title("deploy tokens") 1hriojskpltmunq
65 toolkit.print_line() 1hriojskpltmunq
67 if not data.tokens: 1hriojskpltmunq
68 toolkit.print("No deploy tokens found.", bullet=False) 1rosptuq
69 return 1rosptuq
71 toolkit.print(_get_deploy_tokens_table(data.tokens), bullet=False) 1hijklmn
74@tokens_app.command("list", cls=UserCommand) 1abcdefg
75def list_tokens( 1abQcdRefgS
76 ctx: typer.Context,
77 app_id: Annotated[
78 str | None,
79 typer.Option(
80 "--app-id",
81 help="ID of the app whose deploy tokens should be listed.",
82 ),
83 ] = None,
84 json_output: JsonOutputOption = False,
85) -> Any:
86 """
87 List deploy tokens for an app.
88 """
90 toolkit = get_user_command_context(ctx).toolkit 1vwhrJxyioKzAjsLBCkpMDEltNFGmuOHInqP
92 target_app_id = resolve_app_id_or_fail(toolkit, app_id=app_id) 1vwhrJxyioKzAjsLBCkpMDEltNFGmuOHInqP
94 with APIClient() as client: 1vwhrxyiozAjsBCkpDEltFGmuHInq
95 with toolkit.progress( 1vwhrxyiozAjsBCkpDEltFGmuHInq
96 title="Fetching deploy tokens",
97 transient=True,
98 ) as progress:
99 with client.handle_http_errors( 1vwhrxyiozAjsBCkpDEltFGmuHInq
100 progress,
101 default_message="Error fetching deploy tokens. Please try again later.",
102 not_found_message="App not found.",
103 toolkit=toolkit,
104 ):
105 tokens = _get_deploy_tokens(client=client, app_id=target_app_id) 1vwhrxyiozAjsBCkpDEltFGmuHInq
107 toolkit.success( 1vwhrxyiozAjsBCkpDEltFGmuHInq
108 DeployTokensListOutput(app_id=target_app_id, tokens=tokens.data),
109 render_output=_render_deploy_tokens_list_output,
110 )