Coverage for osmclient/cli_commands/repo.py: 46%
227 statements
« prev ^ index » next coverage.py v7.3.1, created at 2024-06-22 09:01 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2024-06-22 09:01 +0000
1# Copyright ETSI Contributors and Others.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16import click
17from osmclient.common.exceptions import NotFound, ClientException
18from osmclient.cli_commands import utils
19from prettytable import PrettyTable
20import yaml
21import json
22import logging
24logger = logging.getLogger("osmclient")
27@click.command(name="repo-add", short_help="adds a repo to OSM")
28@click.argument("name")
29@click.argument("uri")
30@click.option(
31 "--type",
32 type=click.Choice(["osm", "helm-chart", "juju-bundle"]),
33 default="osm",
34 help="type of repo (osm for OSM repositories, helm-chart for Helm Charts, juju-bundle for Juju Bundles)",
35)
36@click.option("--description", default=None, help="human readable description")
37@click.option(
38 "--user", default=None, help="OSM repository: The username of the OSM repository"
39)
40@click.option(
41 "--password",
42 default=None,
43 help="OSM repository: The password of the OSM repository",
44)
45@click.option(
46 "--oci",
47 is_flag=True,
48 help="enable OCI (only for helm-chart repos, default: false, automatically set to true for oci:// URI)",
49)
50@click.option(
51 "--ca-file",
52 default=None,
53 help="cert to use when adding a repository (only for helm)",
54)
55@click.pass_context
56def repo_add(ctx, **kwargs):
57 """adds a repo to OSM
59 NAME: name of the repo
60 URI: URI of the repo
61 """
62 kwargs = {k: v for k, v in kwargs.items() if v is not None}
63 repo = kwargs
64 repo["url"] = repo.pop("uri")
65 if repo["url"].startswith("oci://"):
66 repo["oci"] = True
67 if "ca_file" in kwargs:
68 try:
69 with open(kwargs["ca_file"], "r") as ca_cert:
70 repo["cacert"] = ca_cert.read()
71 repo.pop("ca_file")
72 except FileNotFoundError:
73 raise ClientException("CA file not found !")
74 except EOFError:
75 raise ClientException("Empty CA file !")
76 except PermissionError:
77 raise ClientException("Can not read CA file ! Insufficient permissions")
78 except Exception as e:
79 raise ClientException(f"Can not read the cert file ! Error: {e}")
80 if repo["type"] in ["helm-chart", "juju-bundle"]:
81 ctx.obj.repo.create(repo["name"], repo)
82 else:
83 ctx.obj.osmrepo.create(repo["name"], repo)
86@click.command(name="repo-update", short_help="updates a repo in OSM")
87@click.argument("name")
88@click.option("--newname", help="New name for the repo")
89@click.option("--uri", help="URI of the repo")
90@click.option("--description", help="human readable description")
91@click.option(
92 "--oci",
93 is_flag=True,
94 help="enable OCI (only for helm-chart repos, default: false, automatically set to true for oci:// URI)",
95)
96@click.pass_context
97def repo_update(ctx, name, newname, uri, description, oci):
98 """updates a repo in OSM
100 NAME: name of the repo
101 """
102 utils.check_client_version(ctx.obj, ctx.command.name)
103 repo = {}
104 if newname:
105 repo["name"] = newname
106 if uri:
107 repo["url"] = uri
108 if uri.startswith("oci://"):
109 repo["oci"] = True
110 if description:
111 repo["description"] = description
112 if oci:
113 repo["oci"] = oci
114 try:
115 ctx.obj.repo.update(name, repo)
116 except NotFound:
117 ctx.obj.osmrepo.update(name, repo)
120@click.command(
121 name="repo-index", short_help="Index a repository from a folder with artifacts"
122)
123@click.option(
124 "--origin", default=".", help="origin path where the artifacts are located"
125)
126@click.option(
127 "--destination", default=".", help="destination path where the index is deployed"
128)
129@click.pass_context
130def repo_index(ctx, origin, destination):
131 """Index a repository
133 NAME: name or ID of the repo to be deleted
134 """
135 utils.check_client_version(ctx.obj, ctx.command.name)
136 ctx.obj.osmrepo.repo_index(origin, destination)
139@click.command(name="repo-delete", short_help="deletes a repo")
140@click.argument("name")
141@click.option(
142 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
143)
144@click.pass_context
145def repo_delete(ctx, name, force):
146 """deletes a repo
148 NAME: name or ID of the repo to be deleted
149 """
150 logger.debug("")
151 try:
152 ctx.obj.repo.delete(name, force=force)
153 except NotFound:
154 ctx.obj.osmrepo.delete(name, force=force)
157@click.command(name="repo-list")
158@click.option(
159 "--filter",
160 default=None,
161 multiple=True,
162 help="restricts the list to the repos matching the filter",
163)
164@click.option("--literal", is_flag=True, help="print literally, no pretty table")
165@click.pass_context
166def repo_list(ctx, filter, literal):
167 """list all repos"""
168 # K8s Repositories
169 utils.check_client_version(ctx.obj, ctx.command.name)
170 if filter:
171 filter = "&".join(filter)
172 resp = ctx.obj.repo.list(filter)
173 resp += ctx.obj.osmrepo.list(filter)
174 if literal:
175 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
176 return
177 table = PrettyTable(["Name", "Id", "Type", "URI", "Description"])
178 for repo in resp:
179 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
180 table.add_row(
181 [
182 repo["name"],
183 repo["_id"],
184 repo["type"],
185 repo["url"],
186 utils.trunc_text(repo.get("description") or "", 40),
187 ]
188 )
189 table.align = "l"
190 print(table)
193@click.command(name="repo-show", short_help="shows the details of a repo")
194@click.argument("name")
195@click.option("--literal", is_flag=True, help="print literally, no pretty table")
196@click.pass_context
197def repo_show(ctx, name, literal):
198 """shows the details of a repo
200 NAME: name or ID of the repo
201 """
202 try:
203 resp = ctx.obj.repo.get(name)
204 except NotFound:
205 resp = ctx.obj.osmrepo.get(name)
207 if literal:
208 if resp:
209 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
210 return
211 table = PrettyTable(["key", "attribute"])
212 if resp:
213 for k, v in list(resp.items()):
214 table.add_row([k, json.dumps(v, indent=2)])
216 table.align = "l"
217 print(table)
220########################
221# Catalogue commands
222########################
225def pkg_repo_list(ctx, pkgtype, filter, repo, long):
226 resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo)
227 if long:
228 table = PrettyTable(
229 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
230 )
231 else:
232 table = PrettyTable(["nfpkg name", "repository"])
233 for vnfd in resp:
234 name = vnfd.get("id", vnfd.get("name", "-"))
235 repository = vnfd.get("repository")
236 if long:
237 vendor = vnfd.get("provider", vnfd.get("vendor"))
238 version = vnfd.get("version")
239 description = vnfd.get("description")
240 latest = vnfd.get("latest")
241 table.add_row([name, vendor, version, latest, description, repository])
242 else:
243 table.add_row([name, repository])
244 table.align = "l"
245 print(table)
248def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal):
249 logger.debug("")
250 if filter:
251 filter = "&".join(filter)
252 resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter)
254 if literal:
255 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
256 return
257 pkgtype += "d"
258 catalog = pkgtype + "-catalog"
259 full_catalog = pkgtype + ":" + catalog
260 if resp.get(catalog):
261 resp = resp.pop(catalog)[pkgtype][0]
262 elif resp.get(full_catalog):
263 resp = resp.pop(full_catalog)[pkgtype][0]
265 table = PrettyTable(["field", "value"])
266 for k, v in list(resp.items()):
267 table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
268 table.align = "l"
269 print(table)
272@click.command(name="vnfpkg-repo-list", short_help="list all xNF from OSM repositories")
273@click.option(
274 "--filter",
275 default=None,
276 multiple=True,
277 help="restricts the list to the NFpkg matching the filter",
278)
279@click.option(
280 "--repo", default=None, help="restricts the list to a particular OSM repository"
281)
282@click.option("--long", is_flag=True, help="get more details")
283@click.pass_context
284def nfpkg_repo_list1(ctx, filter, repo, long):
285 """list xNF packages from OSM repositories"""
286 pkgtype = "vnf"
287 pkg_repo_list(ctx, pkgtype, filter, repo, long)
290@click.command(name="nfpkg-repo-list", short_help="list all xNF from OSM repositories")
291@click.option(
292 "--filter",
293 default=None,
294 multiple=True,
295 help="restricts the list to the NFpkg matching the filter",
296)
297@click.option(
298 "--repo", default=None, help="restricts the list to a particular OSM repository"
299)
300@click.option("--long", is_flag=True, help="get more details")
301@click.pass_context
302def nfpkg_repo_list2(ctx, filter, repo, long):
303 """list xNF packages from OSM repositories"""
304 pkgtype = "vnf"
305 pkg_repo_list(ctx, pkgtype, filter, repo, long)
308@click.command(name="nsd-repo-list", short_help="list all NS from OSM repositories")
309@click.option(
310 "--filter",
311 default=None,
312 multiple=True,
313 help="restricts the list to the NS matching the filter",
314)
315@click.option(
316 "--repo", default=None, help="restricts the list to a particular OSM repository"
317)
318@click.option("--long", is_flag=True, help="get more details")
319@click.pass_context
320def nspkg_repo_list(ctx, filter, repo, long):
321 """list xNF packages from OSM repositories"""
322 pkgtype = "ns"
323 pkg_repo_list(ctx, pkgtype, filter, repo, long)
326@click.command(name="nspkg-repo-list", short_help="list all NS from OSM repositories")
327@click.option(
328 "--filter",
329 default=None,
330 multiple=True,
331 help="restricts the list to the NS matching the filter",
332)
333@click.option(
334 "--repo", default=None, help="restricts the list to a particular OSM repository"
335)
336@click.option("--long", is_flag=True, help="get more details")
337@click.pass_context
338def nspkg_repo_list2(ctx, filter, repo, long):
339 """list xNF packages from OSM repositories"""
340 pkgtype = "ns"
341 pkg_repo_list(ctx, pkgtype, filter, repo, long)
344@click.command(
345 name="vnfpkg-repo-show",
346 short_help="shows the details of a NF package in an OSM repository",
347)
348@click.option("--literal", is_flag=True, help="print literally, no pretty table")
349@click.option("--repo", required=True, help="Repository name")
350@click.argument("name")
351@click.option("--filter", default=None, multiple=True, help="filter by fields")
352@click.option("--version", default="latest", help="package version")
353@click.pass_context
354def vnfd_show1(ctx, name, repo, version, literal=None, filter=None):
355 """shows the content of a VNFD in a repository
357 NAME: name or ID of the VNFD/VNFpkg
358 """
359 pkgtype = "vnf"
360 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
363@click.command(
364 name="nsd-repo-show",
365 short_help="shows the details of a NS package in an OSM repository",
366)
367@click.option("--literal", is_flag=True, help="print literally, no pretty table")
368@click.option("--repo", required=True, help="Repository name")
369@click.argument("name")
370@click.option("--filter", default=None, multiple=True, help="filter by fields")
371@click.option("--version", default="latest", help="package version")
372@click.pass_context
373def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None):
374 """shows the content of a VNFD in a repository
376 NAME: name or ID of the VNFD/VNFpkg
377 """
378 pkgtype = "ns"
379 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
382@click.command(
383 name="nspkg-repo-show",
384 short_help="shows the details of a NS package in an OSM repository",
385)
386@click.option("--literal", is_flag=True, help="print literally, no pretty table")
387@click.option("--repo", required=True, help="Repository name")
388@click.argument("name")
389@click.option("--filter", default=None, multiple=True, help="filter by fields")
390@click.option("--version", default="latest", help="package version")
391@click.pass_context
392def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None):
393 """shows the content of a VNFD in a repository
395 NAME: name or ID of the VNFD/VNFpkg
396 """
397 pkgtype = "ns"
398 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
401@click.command(
402 name="nfpkg-repo-show",
403 short_help="shows the details of a NF package in an OSM repository",
404)
405@click.option("--literal", is_flag=True, help="print literally, no pretty table")
406@click.option("--repo", required=True, help="Repository name")
407@click.argument("name")
408@click.option("--filter", default=None, multiple=True, help="filter by fields")
409@click.option("--version", default="latest", help="package version")
410@click.pass_context
411def vnfd_show2(ctx, name, repo, version, literal=None, filter=None):
412 """shows the content of a VNFD in a repository
414 NAME: name or ID of the VNFD/VNFpkg
415 """
416 pkgtype = "vnf"
417 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)