Fix bug 2176 to update properly VCA without modifying the name
[osm/osmclient.git] / osmclient / cli_commands / vca.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 ClientException
18 from osmclient.cli_commands import utils
19 from prettytable import PrettyTable
20 import yaml
21 import json
22 import os
23 from typing import Any, Dict
24 import logging
25
26 logger = logging.getLogger("osmclient")
27
28
29 @click.command(name="vca-add", short_help="adds a VCA (Juju controller) to OSM")
30 @click.argument("name")
31 @click.option(
32 "--endpoints",
33 prompt=True,
34 help="Comma-separated list of IP or hostnames of the Juju controller",
35 )
36 @click.option("--user", prompt=True, help="Username with admin priviledges")
37 @click.option("--secret", prompt=True, help="Password of the specified username")
38 @click.option("--cacert", prompt=True, help="CA certificate")
39 @click.option(
40 "--lxd-cloud",
41 prompt=True,
42 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
43 )
44 @click.option(
45 "--lxd-credentials",
46 prompt=True,
47 help="Name of the cloud credentialsto be used for the LXD cloud",
48 )
49 @click.option(
50 "--k8s-cloud",
51 prompt=True,
52 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
53 )
54 @click.option(
55 "--k8s-credentials",
56 prompt=True,
57 help="Name of the cloud credentialsto be used for the K8s cloud",
58 )
59 @click.option(
60 "--model-config",
61 default={},
62 help="Configuration options for the models",
63 )
64 @click.option("--description", default=None, help="human readable description")
65 @click.pass_context
66 def vca_add(
67 ctx,
68 name,
69 endpoints,
70 user,
71 secret,
72 cacert,
73 lxd_cloud,
74 lxd_credentials,
75 k8s_cloud,
76 k8s_credentials,
77 model_config,
78 description,
79 ):
80 """adds a VCA to OSM
81
82 NAME: name of the VCA
83 """
84 logger.debug("")
85 utils.check_client_version(ctx.obj, ctx.command.name)
86 vca = {}
87 vca["name"] = name
88 vca["endpoints"] = endpoints.split(",")
89 vca["user"] = user
90 vca["secret"] = secret
91 vca["cacert"] = cacert
92 vca["lxd-cloud"] = lxd_cloud
93 vca["lxd-credentials"] = lxd_credentials
94 vca["k8s-cloud"] = k8s_cloud
95 vca["k8s-credentials"] = k8s_credentials
96 if description:
97 vca["description"] = description
98 if model_config:
99 model_config = load(model_config)
100 vca["model-config"] = model_config
101 ctx.obj.vca.create(name, vca)
102
103
104 def load(data: Any):
105 logger.debug("")
106 if os.path.isfile(data):
107 return load_file(data)
108 else:
109 try:
110 return json.loads(data)
111 except ValueError as e:
112 raise ClientException(e)
113
114
115 def load_file(file_path: str) -> Dict:
116 logger.debug("")
117 content = None
118 with open(file_path, "r") as f:
119 content = f.read()
120 try:
121 return yaml.safe_load(content)
122 except yaml.scanner.ScannerError:
123 pass
124 try:
125 return json.loads(content)
126 except ValueError:
127 pass
128 raise ClientException(f"{file_path} must be a valid yaml or json file")
129
130
131 @click.command(name="vca-update", short_help="updates a VCA")
132 @click.argument("name")
133 @click.option(
134 "--endpoints", help="Comma-separated list of IP or hostnames of the Juju controller"
135 )
136 @click.option("--newname", help="New name for the VCA")
137 @click.option("--user", help="Username with admin priviledges")
138 @click.option("--secret", help="Password of the specified username")
139 @click.option("--cacert", help="CA certificate")
140 @click.option(
141 "--lxd-cloud",
142 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
143 )
144 @click.option(
145 "--lxd-credentials",
146 help="Name of the cloud credentialsto be used for the LXD cloud",
147 )
148 @click.option(
149 "--k8s-cloud",
150 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
151 )
152 @click.option(
153 "--k8s-credentials",
154 help="Name of the cloud credentialsto be used for the K8s cloud",
155 )
156 @click.option(
157 "--model-config",
158 help="Configuration options for the models",
159 )
160 @click.option("--description", default=None, help="human readable description")
161 @click.pass_context
162 def vca_update(
163 ctx,
164 name,
165 newname,
166 endpoints,
167 user,
168 secret,
169 cacert,
170 lxd_cloud,
171 lxd_credentials,
172 k8s_cloud,
173 k8s_credentials,
174 model_config,
175 description,
176 ):
177 """updates a VCA
178
179 NAME: name or ID of the VCA
180 """
181 logger.debug("")
182 utils.check_client_version(ctx.obj, ctx.command.name)
183 vca = {}
184 if newname:
185 vca["name"] = newname
186 if endpoints:
187 vca["endpoints"] = endpoints.split(",")
188 if user:
189 vca["user"] = user
190 if secret:
191 vca["secret"] = secret
192 if cacert:
193 vca["cacert"] = cacert
194 if lxd_cloud:
195 vca["lxd-cloud"] = lxd_cloud
196 if lxd_credentials:
197 vca["lxd-credentials"] = lxd_credentials
198 if k8s_cloud:
199 vca["k8s-cloud"] = k8s_cloud
200 if k8s_credentials:
201 vca["k8s-credentials"] = k8s_credentials
202 if description:
203 vca["description"] = description
204 if model_config:
205 model_config = load(model_config)
206 vca["model-config"] = model_config
207 ctx.obj.vca.update(name, vca)
208
209
210 @click.command(name="vca-delete", short_help="deletes a VCA")
211 @click.argument("name")
212 @click.option(
213 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
214 )
215 @click.pass_context
216 def vca_delete(ctx, name, force):
217 """deletes a VCA
218
219 NAME: name or ID of the VCA to be deleted
220 """
221 logger.debug("")
222 utils.check_client_version(ctx.obj, ctx.command.name)
223 ctx.obj.vca.delete(name, force=force)
224
225
226 @click.command(name="vca-list")
227 @click.option(
228 "--filter",
229 default=None,
230 multiple=True,
231 help="restricts the list to the VCAs matching the filter",
232 )
233 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
234 @click.option("--long", is_flag=True, help="get more details")
235 @click.pass_context
236 def vca_list(ctx, filter, literal, long):
237 """list VCAs"""
238 logger.debug("")
239 utils.check_client_version(ctx.obj, ctx.command.name)
240 if filter:
241 filter = "&".join(filter)
242 resp = ctx.obj.vca.list(filter)
243 if literal:
244 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
245 return
246 if long:
247 table = PrettyTable(
248 ["Name", "Id", "Project", "Operational State", "Detailed Status"]
249 )
250 project_list = ctx.obj.project.list()
251 else:
252 table = PrettyTable(["Name", "Id", "Operational State"])
253 for vca in resp:
254 logger.debug("VCA details: {}".format(yaml.safe_dump(vca)))
255 if long:
256 project_id, project_name = utils.get_project(project_list, vca)
257 detailed_status = vca.get("_admin", {}).get("detailed-status", "-")
258 table.add_row(
259 [
260 vca["name"],
261 vca["_id"],
262 project_name,
263 vca.get("_admin", {}).get("operationalState", "-"),
264 utils.wrap_text(text=detailed_status, width=40),
265 ]
266 )
267 else:
268 table.add_row(
269 [
270 vca["name"],
271 vca["_id"],
272 vca.get("_admin", {}).get("operationalState", "-"),
273 ]
274 )
275 table.align = "l"
276 print(table)
277
278
279 @click.command(name="vca-show", short_help="shows the details of a VCA")
280 @click.argument("name")
281 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
282 @click.pass_context
283 def vca_show(ctx, name, literal):
284 """shows the details of a VCA
285
286 NAME: name or ID of the VCA
287 """
288 logger.debug("")
289 resp = ctx.obj.vca.get(name)
290 if literal:
291 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
292 return
293 table = PrettyTable(["key", "attribute"])
294 for k, v in list(resp.items()):
295 table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
296 table.align = "l"
297 print(table)