Feature 10997: add oci flag as new property in helm-chart repos
[osm/osmclient.git] / osmclient / cli_commands / repo.py
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.
15
16 import click
17 from osmclient.common.exceptions import NotFound
18 from osmclient.cli_commands import utils
19 from prettytable import PrettyTable
20 import yaml
21 import json
22 import logging
23
24 logger = logging.getLogger("osmclient")
25
26
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.pass_context
51 def repo_add(ctx, **kwargs):
52 """adds a repo to OSM
53
54 NAME: name of the repo
55 URI: URI of the repo
56 """
57 kwargs = {k: v for k, v in kwargs.items() if v is not None}
58 repo = kwargs
59 repo["url"] = repo.pop("uri")
60 if repo["url"].startswith("oci://"):
61 repo["oci"] = True
62 if repo["type"] in ["helm-chart", "juju-bundle"]:
63 ctx.obj.repo.create(repo["name"], repo)
64 else:
65 ctx.obj.osmrepo.create(repo["name"], repo)
66
67
68 @click.command(name="repo-update", short_help="updates a repo in OSM")
69 @click.argument("name")
70 @click.option("--newname", help="New name for the repo")
71 @click.option("--uri", help="URI of the repo")
72 @click.option("--description", help="human readable description")
73 @click.option(
74 "--oci",
75 is_flag=True,
76 help="enable OCI (only for helm-chart repos, default: false, automatically set to true for oci:// URI)",
77 )
78 @click.pass_context
79 def repo_update(ctx, name, newname, uri, description, oci):
80 """updates a repo in OSM
81
82 NAME: name of the repo
83 """
84 utils.check_client_version(ctx.obj, ctx.command.name)
85 repo = {}
86 if newname:
87 repo["name"] = newname
88 if uri:
89 repo["url"] = uri
90 if uri.startswith("oci://"):
91 repo["oci"] = True
92 if description:
93 repo["description"] = description
94 if oci:
95 repo["oci"] = oci
96 try:
97 ctx.obj.repo.update(name, repo)
98 except NotFound:
99 ctx.obj.osmrepo.update(name, repo)
100
101
102 @click.command(
103 name="repo-index", short_help="Index a repository from a folder with artifacts"
104 )
105 @click.option(
106 "--origin", default=".", help="origin path where the artifacts are located"
107 )
108 @click.option(
109 "--destination", default=".", help="destination path where the index is deployed"
110 )
111 @click.pass_context
112 def repo_index(ctx, origin, destination):
113 """Index a repository
114
115 NAME: name or ID of the repo to be deleted
116 """
117 utils.check_client_version(ctx.obj, ctx.command.name)
118 ctx.obj.osmrepo.repo_index(origin, destination)
119
120
121 @click.command(name="repo-delete", short_help="deletes a repo")
122 @click.argument("name")
123 @click.option(
124 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
125 )
126 @click.pass_context
127 def repo_delete(ctx, name, force):
128 """deletes a repo
129
130 NAME: name or ID of the repo to be deleted
131 """
132 logger.debug("")
133 try:
134 ctx.obj.repo.delete(name, force=force)
135 except NotFound:
136 ctx.obj.osmrepo.delete(name, force=force)
137
138
139 @click.command(name="repo-list")
140 @click.option(
141 "--filter",
142 default=None,
143 multiple=True,
144 help="restricts the list to the repos matching the filter",
145 )
146 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
147 @click.pass_context
148 def repo_list(ctx, filter, literal):
149 """list all repos"""
150 # K8s Repositories
151 utils.check_client_version(ctx.obj, ctx.command.name)
152 if filter:
153 filter = "&".join(filter)
154 resp = ctx.obj.repo.list(filter)
155 resp += ctx.obj.osmrepo.list(filter)
156 if literal:
157 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
158 return
159 table = PrettyTable(["Name", "Id", "Type", "URI", "Description"])
160 for repo in resp:
161 # cluster['k8s-nets'] = json.dumps(yaml.safe_load(cluster['k8s-nets']))
162 table.add_row(
163 [
164 repo["name"],
165 repo["_id"],
166 repo["type"],
167 repo["url"],
168 utils.trunc_text(repo.get("description") or "", 40),
169 ]
170 )
171 table.align = "l"
172 print(table)
173
174
175 @click.command(name="repo-show", short_help="shows the details of a repo")
176 @click.argument("name")
177 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
178 @click.pass_context
179 def repo_show(ctx, name, literal):
180 """shows the details of a repo
181
182 NAME: name or ID of the repo
183 """
184 try:
185 resp = ctx.obj.repo.get(name)
186 except NotFound:
187 resp = ctx.obj.osmrepo.get(name)
188
189 if literal:
190 if resp:
191 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
192 return
193 table = PrettyTable(["key", "attribute"])
194 if resp:
195 for k, v in list(resp.items()):
196 table.add_row([k, json.dumps(v, indent=2)])
197
198 table.align = "l"
199 print(table)
200
201
202 ########################
203 # Catalogue commands
204 ########################
205
206
207 def pkg_repo_list(ctx, pkgtype, filter, repo, long):
208 resp = ctx.obj.osmrepo.pkg_list(pkgtype, filter, repo)
209 if long:
210 table = PrettyTable(
211 ["nfpkg name", "vendor", "version", "latest", "description", "repository"]
212 )
213 else:
214 table = PrettyTable(["nfpkg name", "repository"])
215 for vnfd in resp:
216 name = vnfd.get("id", vnfd.get("name", "-"))
217 repository = vnfd.get("repository")
218 if long:
219 vendor = vnfd.get("provider", vnfd.get("vendor"))
220 version = vnfd.get("version")
221 description = vnfd.get("description")
222 latest = vnfd.get("latest")
223 table.add_row([name, vendor, version, latest, description, repository])
224 else:
225 table.add_row([name, repository])
226 table.align = "l"
227 print(table)
228
229
230 def pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal):
231 logger.debug("")
232 if filter:
233 filter = "&".join(filter)
234 resp = ctx.obj.osmrepo.pkg_get(pkgtype, name, repo, version, filter)
235
236 if literal:
237 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
238 return
239 pkgtype += "d"
240 catalog = pkgtype + "-catalog"
241 full_catalog = pkgtype + ":" + catalog
242 if resp.get(catalog):
243 resp = resp.pop(catalog)[pkgtype][0]
244 elif resp.get(full_catalog):
245 resp = resp.pop(full_catalog)[pkgtype][0]
246
247 table = PrettyTable(["field", "value"])
248 for k, v in list(resp.items()):
249 table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
250 table.align = "l"
251 print(table)
252
253
254 @click.command(name="vnfpkg-repo-list", short_help="list all xNF from OSM repositories")
255 @click.option(
256 "--filter",
257 default=None,
258 multiple=True,
259 help="restricts the list to the NFpkg matching the filter",
260 )
261 @click.option(
262 "--repo", default=None, help="restricts the list to a particular OSM repository"
263 )
264 @click.option("--long", is_flag=True, help="get more details")
265 @click.pass_context
266 def nfpkg_repo_list1(ctx, filter, repo, long):
267 """list xNF packages from OSM repositories"""
268 pkgtype = "vnf"
269 pkg_repo_list(ctx, pkgtype, filter, repo, long)
270
271
272 @click.command(name="nfpkg-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
284 def nfpkg_repo_list2(ctx, filter, repo, long):
285 """list xNF packages from OSM repositories"""
286 pkgtype = "vnf"
287 pkg_repo_list(ctx, pkgtype, filter, repo, long)
288
289
290 @click.command(name="nsd-repo-list", short_help="list all NS from OSM repositories")
291 @click.option(
292 "--filter",
293 default=None,
294 multiple=True,
295 help="restricts the list to the NS 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
302 def nspkg_repo_list(ctx, filter, repo, long):
303 """list xNF packages from OSM repositories"""
304 pkgtype = "ns"
305 pkg_repo_list(ctx, pkgtype, filter, repo, long)
306
307
308 @click.command(name="nspkg-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
320 def nspkg_repo_list2(ctx, filter, repo, long):
321 """list xNF packages from OSM repositories"""
322 pkgtype = "ns"
323 pkg_repo_list(ctx, pkgtype, filter, repo, long)
324
325
326 @click.command(
327 name="vnfpkg-repo-show",
328 short_help="shows the details of a NF package in an OSM repository",
329 )
330 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
331 @click.option("--repo", required=True, help="Repository name")
332 @click.argument("name")
333 @click.option("--filter", default=None, multiple=True, help="filter by fields")
334 @click.option("--version", default="latest", help="package version")
335 @click.pass_context
336 def vnfd_show1(ctx, name, repo, version, literal=None, filter=None):
337 """shows the content of a VNFD in a repository
338
339 NAME: name or ID of the VNFD/VNFpkg
340 """
341 pkgtype = "vnf"
342 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
343
344
345 @click.command(
346 name="nsd-repo-show",
347 short_help="shows the details of a NS package in an OSM repository",
348 )
349 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
350 @click.option("--repo", required=True, help="Repository name")
351 @click.argument("name")
352 @click.option("--filter", default=None, multiple=True, help="filter by fields")
353 @click.option("--version", default="latest", help="package version")
354 @click.pass_context
355 def nsd_repo_show(ctx, name, repo, version, literal=None, filter=None):
356 """shows the content of a VNFD in a repository
357
358 NAME: name or ID of the VNFD/VNFpkg
359 """
360 pkgtype = "ns"
361 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
362
363
364 @click.command(
365 name="nspkg-repo-show",
366 short_help="shows the details of a NS package in an OSM repository",
367 )
368 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
369 @click.option("--repo", required=True, help="Repository name")
370 @click.argument("name")
371 @click.option("--filter", default=None, multiple=True, help="filter by fields")
372 @click.option("--version", default="latest", help="package version")
373 @click.pass_context
374 def nsd_repo_show2(ctx, name, repo, version, literal=None, filter=None):
375 """shows the content of a VNFD in a repository
376
377 NAME: name or ID of the VNFD/VNFpkg
378 """
379 pkgtype = "ns"
380 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)
381
382
383 @click.command(
384 name="nfpkg-repo-show",
385 short_help="shows the details of a NF package in an OSM repository",
386 )
387 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
388 @click.option("--repo", required=True, help="Repository name")
389 @click.argument("name")
390 @click.option("--filter", default=None, multiple=True, help="filter by fields")
391 @click.option("--version", default="latest", help="package version")
392 @click.pass_context
393 def vnfd_show2(ctx, name, repo, version, literal=None, filter=None):
394 """shows the content of a VNFD in a repository
395
396 NAME: name or ID of the VNFD/VNFpkg
397 """
398 pkgtype = "vnf"
399 pkg_repo_show(ctx, pkgtype, name, repo, version, filter, literal)