Coverage for src/fastapi_cloud_cli/commands/domains/restart.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 1opqrstu
3import typer 1opqrstu
4from pydantic import BaseModel, Field 1opqrstu
5from rich_toolkit import RichToolkit 1opqrstu
7from fastapi_cloud_cli.api import APIClient, CustomDomain 1opqrstu
8from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context 1opqrstu
9from fastapi_cloud_cli.commands.domains._app import domains_app 1opqrstu
10from fastapi_cloud_cli.commands.domains._shared import ( 1opqrstu
11 _find_custom_domain,
12 _select_custom_domain,
13)
14from fastapi_cloud_cli.commands.domains.rendering import render_custom_domain_details 1opqrstu
15from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail 1opqrstu
16from fastapi_cloud_cli.utils.execution import JsonOutputOption 1opqrstu
19class CustomDomainRestartOutput(BaseModel): 1opqrstu
20 app_id: str 1opqrstu
21 domain: CustomDomain 1opqrstu
22 show_title: Annotated[bool, Field(exclude=True)] = True 1opqrstu
25def _render_custom_domain_restart_output( 1opjqrkstul
26 data: CustomDomainRestartOutput,
27 toolkit: RichToolkit,
28) -> None:
29 if data.show_title: 1acdjemfkbghnil
30 toolkit.print_title("custom domains") 1cjmkgnl
31 toolkit.print_line() 1cjmkgnl
33 toolkit.print( 1acdjemfkbghnil
34 f"Restarted verification for [bold]{data.domain.name}[/bold]",
35 emoji="🐔",
36 )
37 toolkit.print_line() 1acdjemfkbghnil
38 render_custom_domain_details(data.domain, toolkit) 1acdjemfkbghnil
39 toolkit.print_line() 1acdjemfkbghnil
40 toolkit.print( 1acdjemfkbghnil
41 "[dim]hint: Run `fastapi cloud domains get "
42 f"{data.domain.name}` to check progress.[/dim]"
43 )
46@domains_app.command("restart", cls=UserCommand) 1opqrstu
47def restart_domain( 1op4qr5stu6
48 ctx: typer.Context,
49 domain: Annotated[
50 str | None,
51 typer.Argument(
52 help="Hostname or ID of the custom domain whose setup should restart.",
53 ),
54 ] = None,
55 app_id: Annotated[
56 str | None,
57 typer.Option(
58 "--app-id",
59 help="ID of the app that owns the custom domain.",
60 ),
61 ] = None,
62 json_output: JsonOutputOption = False,
63) -> Any:
64 """
65 Restart failed custom domain setup for an app.
66 """
67 toolkit = get_user_command_context(ctx).toolkit 1XLvwazcYSGAdMjZTHBeNm0UICfOk1PxybDg2VJEhQn3WKFiRl
68 app_id = resolve_app_id_or_fail(toolkit, app_id=app_id) 1XLvwazcYSGAdMjZTHBeNm0UICfOk1PxybDg2VJEhQn3WKFiRl
69 domain_was_provided = domain is not None 1XLvwazcYSGAdMjZTHBeNm0UICfOk1PxybDg2VJEhQn3WKFiRl
71 if domain is None and toolkit.mode == "json": 1XLvwazcYSGAdMjZTHBeNm0UICfOk1PxybDg2VJEhQn3WKFiRl
72 toolkit.fail( 1XYZ0123
73 "missing_required_input",
74 "Custom domain is required.",
75 hint="Pass DOMAIN to choose a custom domain.",
76 )
78 with APIClient() as client: 1LvwazcSGAdMjTHBeNmUICfOkPxybDgVJEhQnWKFiRl
79 with ( 1LvwazcPxybDg
80 toolkit.progress(
81 title="Fetching custom domains",
82 transient=True,
83 ) as progress,
84 client.handle_http_errors(
85 progress,
86 default_message=(
87 "Error fetching custom domains. Please try again later."
88 ),
89 not_found_message="App not found.",
90 toolkit=toolkit,
91 ),
92 ):
93 domains = client.get_custom_domains(app_id=app_id).data 1LvwazcSGAdMjTHBeNmUICfOkPxybDgVJEhQnWKFiRl
95 selected_domain: CustomDomain | None
96 if domain is None: 1LvwazcSGAdMjTHBeNmUICfOkPxybDgVJEhQnWKFiRl
97 toolkit.print_title("custom domains") 1waAdBeCfybEhFi
98 toolkit.print_line() 1waAdBeCfybEhFi
99 failed_domains = [domain for domain in domains if domain.setup_failed] 1waAdBeCfybEhFi
101 if not failed_domains: 1waAdBeCfybEhFi
102 toolkit.print("No failed custom domains found.", bullet=False) 1wABCyEF
103 return 1wABCyEF
105 selected_domain = _select_custom_domain( 1adefbhi
106 toolkit,
107 failed_domains,
108 prompt="Select the custom domain to restart:",
109 )
110 toolkit.print_line() 1adefbhi
111 else:
112 selected_domain = _find_custom_domain(domains, domain) 1LvzcSGMjTHNmUIOkPxDgVJQnWKRl
113 if selected_domain is None: 1LvzcSGMjTHNmUIOkPxDgVJQnWKRl
114 toolkit.fail( 1LSTUPVW
115 "not_found",
116 f"Custom domain {domain} not found.",
117 hint=(
118 "Run `fastapi cloud domains list` to see available "
119 "custom domains."
120 ),
121 )
123 assert selected_domain is not None 1vazcGdMjHeNmIfOkxbDgJhQnKiRl
124 with ( 1vazcxbDg
125 toolkit.progress(
126 title="Restarting custom domain setup",
127 transient=True,
128 ) as progress,
129 client.handle_http_errors(
130 progress,
131 default_message=(
132 "Error restarting custom domain setup. Please try again later."
133 ),
134 not_found_message="Custom domain not found.",
135 toolkit=toolkit,
136 ),
137 ):
138 restarted_domain = client.restart_custom_domain_setup( 1vazcGdMjHeNmIfOkxbDgJhQnKiRl
139 app_id=app_id,
140 domain_id=selected_domain.id,
141 )
143 toolkit.success( 1vacGdjHemIfkxbgJhnKil
144 CustomDomainRestartOutput(
145 app_id=app_id,
146 domain=restarted_domain,
147 show_title=domain_was_provided,
148 ),
149 render_output=_render_custom_domain_restart_output,
150 )