Coverage for harbor_cli/commands/api/repository.py: 58%

34 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.models.models import Repository 

7 

8from ...logs import logger 

9from ...output.render import render_result 

10from ...state import state 

11from ...utils.commands import inject_help 

12from ...utils.commands import inject_resource_options 

13 

14 

15# Create a command group 

16app = typer.Typer( 

17 name="repository", 

18 help="Manage repositories.", 

19 no_args_is_help=True, 

20) 

21 

22 

23def get_repository(project: str, repository_name: str) -> Repository: 

24 return state.run( 

25 state.client.get_repository(project, repository_name), 

26 "Fetching repository...", 

27 ) 

28 

29 

30# HarborAsyncClient.get_repository() 

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

32def get_reposity_command( 

33 ctx: typer.Context, 

34 project: str = typer.Argument( 

35 ..., 

36 help="Name of the project the repository belongs to.", 

37 ), 

38 repository: str = typer.Argument( 

39 ..., 

40 help="Name of the repository to get.", 

41 ), 

42) -> None: 

43 """Fetch a repository.""" 

44 # TODO: accept single arg like in `harbor-cli artifact get`? 

45 repo = get_repository(project, repository) 

46 render_result(repo, ctx) 

47 

48 

49# HarborAsyncClient.delete_repository() 

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

51def delete_artifact( 

52 ctx: typer.Context, 

53 project: str = typer.Argument( 

54 ..., 

55 help="Name of the project the repository belongs to.", 

56 ), 

57 repository: str = typer.Argument( 

58 ..., 

59 help="Name of the repository to get.", 

60 ), 

61 force: bool = typer.Option( 

62 False, 

63 "--force", 

64 "-f", 

65 help="Skip confirmation prompt.", 

66 ), 

67) -> None: 

68 """Delete a repository.""" 

69 if not force: 

70 typer.confirm( 

71 f"Are you sure you want to delete {project}/{repository}?", 

72 abort=True, 

73 ) 

74 state.run( 

75 state.client.delete_repository( 

76 project, 

77 repository, 

78 ), 

79 "Deleting repository...", 

80 ) 

81 logger.info(f"Deleted {project}/{repository}.") 

82 

83 

84# HarborAsyncClient.update_repository() 

85@app.command("update") 

86@inject_help(Repository) 

87def update_repository( 

88 ctx: typer.Context, 

89 project: str = typer.Argument( 

90 ..., 

91 help="Project name of repository to update.", 

92 ), 

93 repository: str = typer.Argument( 

94 ..., 

95 help="Name of the repository to update.", 

96 ), 

97 description: Optional[str] = typer.Option(None), 

98) -> None: 

99 """Update a repository. 

100 

101 As of now, only the description can be updated (if the Web UI is to be trusted). 

102 """ 

103 repo = get_repository(project, repository) 

104 repo.description = description 

105 state.run(state.client.update_repository(project, repository, repo)) 

106 logger.info(f"Updated {project}/{repository}.") 

107 

108 

109# HarborAsyncClient.get_repositories() 

110@app.command("list") 

111@inject_resource_options() 

112def list_repos( 

113 ctx: typer.Context, 

114 project: Optional[str] = typer.Argument( 

115 None, 

116 help="Name of project to fetch repositories from. If not specified, all projects will be searched.", 

117 ), 

118 query: Optional[str] = None, 

119 sort: Optional[str] = None, 

120 page: int = 1, 

121 page_size: int = 10, 

122 limit: Optional[int] = ..., # type: ignore 

123) -> None: 

124 """List repositories in all projects or a specific project.""" 

125 

126 repos = state.run( 

127 state.client.get_repositories( 

128 project, 

129 query=query, 

130 sort=sort, 

131 page=page, 

132 page_size=page_size, 

133 limit=limit, 

134 ), 

135 "Fetching repositories...", 

136 ) 

137 render_result(repos, ctx)