Coverage for harbor_cli/commands/api/registry.py: 60%

70 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-09 12:09 +0100

1from __future__ import annotations 

2 

3from typing import Optional 

4 

5import typer 

6from harborapi.exceptions import NotFound 

7from harborapi.models.models import Registry 

8from harborapi.models.models import RegistryCredential 

9from harborapi.models.models import RegistryPing 

10from harborapi.models.models import RegistryUpdate 

11 

12from ...logs import logger 

13from ...output.console import exit_err 

14from ...output.console import success 

15from ...output.render import render_result 

16from ...state import state 

17from ...utils.args import create_updated_model 

18from ...utils.args import model_params_from_ctx 

19from ...utils.commands import inject_help 

20from ...utils.commands import inject_resource_options 

21 

22# Create a command group 

23app = typer.Typer( 

24 name="registry", 

25 help="Registry management", 

26 no_args_is_help=True, 

27) 

28 

29 

30def get_registry(registry_id: int) -> Registry: 

31 return state.run(state.client.get_registry(registry_id), "Fetching registry...") 

32 

33 

34@app.command("get", no_args_is_help=True) 

35def get_registry_cmd( 

36 ctx: typer.Context, 

37 registry_id: int = typer.Argument( 

38 ..., 

39 help="ID of registry to get.", 

40 ), 

41) -> None: 

42 """Fetch a registry.""" 

43 registry = get_registry(registry_id) 

44 render_result(registry, ctx) 

45 

46 

47@app.command("create", no_args_is_help=True) 

48@inject_help(RegistryCredential) 

49@inject_help(Registry) 

50def create_registry( 

51 ctx: typer.Context, 

52 name: str = typer.Option( 

53 ..., 

54 "--name", 

55 ), 

56 url: str = typer.Option( 

57 ..., 

58 "--url", 

59 ), 

60 credential_type: str = typer.Option( 

61 None, 

62 "--credential-type", 

63 ), 

64 access_key: str = typer.Option( 

65 None, 

66 "--access-key", 

67 ), 

68 access_secret: str = typer.Option( 

69 None, 

70 "--access-secret", 

71 ), 

72 type: str = typer.Option( 

73 None, 

74 "--type", 

75 ), 

76 insecure: bool = typer.Option( 

77 None, 

78 "--insecure", 

79 ), 

80 description: str = typer.Option( 

81 None, 

82 "--description", 

83 ), 

84 # status omitted 

85) -> None: 

86 """Create a new registry.""" 

87 credential = RegistryCredential( 

88 type=credential_type, access_key=access_key, access_secret=access_secret 

89 ) 

90 registry = Registry( 

91 name=name, 

92 url=url, 

93 credential=credential, 

94 type=type, 

95 insecure=insecure, 

96 description=description, 

97 ) 

98 location = state.run(state.client.create_registry(registry), "Creating registry...") 

99 render_result(location, ctx) 

100 

101 

102@app.command("update", no_args_is_help=True) 

103@inject_help(RegistryUpdate) 

104def update_registry( 

105 ctx: typer.Context, 

106 registry_id: int = typer.Argument( 

107 ..., 

108 help="ID of registry to update.", 

109 ), 

110 name: Optional[str] = typer.Option( 

111 None, 

112 "--name", 

113 ), 

114 url: Optional[str] = typer.Option( 

115 None, 

116 "--url", 

117 ), 

118 description: str = typer.Option( 

119 None, 

120 "--description", 

121 ), 

122 credential_type: str = typer.Option( 

123 None, 

124 "--credential-type", 

125 ), 

126 access_key: str = typer.Option( 

127 None, 

128 "--access-key", 

129 ), 

130 access_secret: str = typer.Option( 

131 None, 

132 "--access-secret", 

133 ), 

134 insecure: bool = typer.Option( 

135 None, 

136 "--insecure", 

137 ), 

138 # status omitted 

139) -> None: 

140 """Update a registry.""" 

141 registry = get_registry(registry_id) 

142 req = create_updated_model(registry, RegistryUpdate, ctx) 

143 state.run(state.client.update_registry(registry_id, req), f"Updating registry...") 

144 logger.info("Registry updated successfully.") 

145 

146 

147@app.command("delete", no_args_is_help=True) 

148def delete_registry( 

149 ctx: typer.Context, 

150 registry_id: int = typer.Argument( 

151 ..., 

152 help="ID of registry to delete.", 

153 ), 

154) -> None: 

155 """Delete a registry.""" 

156 state.run(state.client.delete_registry(registry_id), f"Deleting registry...") 

157 logger.info(f"Deleted registry with ID {registry_id}.") 

158 

159 

160@app.command("info", no_args_is_help=True) 

161def get_registry_info( 

162 ctx: typer.Context, 

163 registry_id: int = typer.Argument( 

164 ..., 

165 help="ID of registry to get info for.", 

166 ), 

167) -> None: 

168 """Get information about a registry's triggers and resource filters""" 

169 registry_info = state.run( 

170 state.client.get_registry_info(registry_id), "Fetching registry info..." 

171 ) 

172 render_result(registry_info, ctx) 

173 

174 

175@app.command("adapters", no_args_is_help=True) 

176def get_registry_adapters( 

177 ctx: typer.Context, 

178) -> None: 

179 """Get available adapters""" 

180 registry_adapters = state.run( 

181 state.client.get_registry_adapters(), "Fetching registry adapters..." 

182 ) 

183 render_result(registry_adapters, ctx) 

184 

185 

186@app.command("providers", no_args_is_help=True) 

187def get_registry_providers( 

188 ctx: typer.Context, 

189) -> None: 

190 """List all available registry providers""" 

191 registry_providers = state.run( 

192 state.client.get_registry_providers(), "Fetching registry providers..." 

193 ) 

194 render_result(registry_providers, ctx) 

195 

196 

197@app.command("ping", no_args_is_help=True) 

198@inject_help(RegistryPing) 

199def check_registry_status( 

200 ctx: typer.Context, 

201 registry_id: int = typer.Argument( 

202 ..., 

203 help="ID of registry to get status of.", 

204 ), 

205 type: Optional[str] = typer.Option( 

206 None, 

207 "--type", 

208 ), 

209 url: Optional[str] = typer.Option( 

210 None, 

211 "--url", 

212 ), 

213 credential_type: Optional[str] = typer.Option( 

214 None, 

215 "--credential-type", 

216 ), 

217 access_key: Optional[str] = typer.Option( 

218 None, 

219 "--access-key", 

220 ), 

221 access_secret: Optional[str] = typer.Option( 

222 None, 

223 "--access-secret", 

224 ), 

225 insecure: Optional[bool] = typer.Option( 

226 None, 

227 "--insecure", 

228 is_flag=False, 

229 ), 

230) -> None: 

231 """Ping a registry to see if it's reachable.""" 

232 params = model_params_from_ctx(ctx, RegistryPing) 

233 ping = RegistryPing(id=registry_id, **params) 

234 

235 # NOTE: handle all StatusErrors? or just NotFound? 

236 try: 

237 state.run( 

238 state.client.check_registry_status(ping), 

239 "Pinging registry...", 

240 no_handle=NotFound, 

241 ) 

242 except NotFound: 

243 exit_err(f"Registry (id={registry_id}) not found.") 

244 else: 

245 success(f"Registry (id={registry_id}) is reachable.") 

246 

247 

248@app.command("list") 

249@inject_resource_options() 

250def list_registries( 

251 ctx: typer.Context, 

252 query: Optional[str], 

253 sort: Optional[str], 

254 page: int, 

255 page_size: int, 

256 limit: Optional[int], 

257) -> None: 

258 """List registries.""" 

259 registries = state.run( 

260 state.client.get_registries( 

261 query=query, 

262 sort=sort, 

263 page=page, 

264 page_size=page_size, 

265 limit=limit, 

266 ), 

267 "Fetching registries..", 

268 ) 

269 render_result(registries, ctx)