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

1from typing import Annotated, Any 1opqrstu

2 

3import typer 1opqrstu

4from pydantic import BaseModel, Field 1opqrstu

5from rich_toolkit import RichToolkit 1opqrstu

6 

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

17 

18 

19class CustomDomainRestartOutput(BaseModel): 1opqrstu

20 app_id: str 1opqrstu

21 domain: CustomDomain 1opqrstu

22 show_title: Annotated[bool, Field(exclude=True)] = True 1opqrstu

23 

24 

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

32 

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 ) 

44 

45 

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

70 

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 ) 

77 

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

94 

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

100 

101 if not failed_domains: 1waAdBeCfybEhFi

102 toolkit.print("No failed custom domains found.", bullet=False) 1wABCyEF

103 return 1wABCyEF

104 

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 ) 

122 

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 ) 

142 

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 )