f60f98fb7b1d0631092eafc3743e41cbcf19e666
[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("--user", help="Username with admin priviledges")
137 @click.option("--secret", help="Password of the specified username")
138 @click.option("--cacert", help="CA certificate")
139 @click.option(
140 "--lxd-cloud",
141 help="Name of the cloud that will be used for LXD containers (LXD proxy charms)",
142 )
143 @click.option(
144 "--lxd-credentials",
145 help="Name of the cloud credentialsto be used for the LXD cloud",
146 )
147 @click.option(
148 "--k8s-cloud",
149 help="Name of the cloud that will be used for K8s containers (K8s proxy charms)",
150 )
151 @click.option(
152 "--k8s-credentials",
153 help="Name of the cloud credentialsto be used for the K8s cloud",
154 )
155 @click.option(
156 "--model-config",
157 help="Configuration options for the models",
158 )
159 @click.option("--description", default=None, help="human readable description")
160 @click.pass_context
161 def vca_update(
162 ctx,
163 name,
164 endpoints,
165 user,
166 secret,
167 cacert,
168 lxd_cloud,
169 lxd_credentials,
170 k8s_cloud,
171 k8s_credentials,
172 model_config,
173 description,
174 ):
175 """updates a VCA
176
177 NAME: name or ID of the VCA
178 """
179 logger.debug("")
180 utils.check_client_version(ctx.obj, ctx.command.name)
181 vca = {}
182 vca["name"] = name
183 if endpoints:
184 vca["endpoints"] = endpoints.split(",")
185 if user:
186 vca["user"] = user
187 if secret:
188 vca["secret"] = secret
189 if cacert:
190 vca["cacert"] = cacert
191 if lxd_cloud:
192 vca["lxd-cloud"] = lxd_cloud
193 if lxd_credentials:
194 vca["lxd-credentials"] = lxd_credentials
195 if k8s_cloud:
196 vca["k8s-cloud"] = k8s_cloud
197 if k8s_credentials:
198 vca["k8s-credentials"] = k8s_credentials
199 if description:
200 vca["description"] = description
201 if model_config:
202 model_config = load(model_config)
203 vca["model-config"] = model_config
204 ctx.obj.vca.update(name, vca)
205
206
207 @click.command(name="vca-delete", short_help="deletes a VCA")
208 @click.argument("name")
209 @click.option(
210 "--force", is_flag=True, help="forces the deletion from the DB (not recommended)"
211 )
212 @click.pass_context
213 def vca_delete(ctx, name, force):
214 """deletes a VCA
215
216 NAME: name or ID of the VCA to be deleted
217 """
218 logger.debug("")
219 utils.check_client_version(ctx.obj, ctx.command.name)
220 ctx.obj.vca.delete(name, force=force)
221
222
223 @click.command(name="vca-list")
224 @click.option(
225 "--filter",
226 default=None,
227 multiple=True,
228 help="restricts the list to the VCAs matching the filter",
229 )
230 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
231 @click.option("--long", is_flag=True, help="get more details")
232 @click.pass_context
233 def vca_list(ctx, filter, literal, long):
234 """list VCAs"""
235 logger.debug("")
236 utils.check_client_version(ctx.obj, ctx.command.name)
237 if filter:
238 filter = "&".join(filter)
239 resp = ctx.obj.vca.list(filter)
240 if literal:
241 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
242 return
243 if long:
244 table = PrettyTable(
245 ["Name", "Id", "Project", "Operational State", "Detailed Status"]
246 )
247 project_list = ctx.obj.project.list()
248 else:
249 table = PrettyTable(["Name", "Id", "Operational State"])
250 for vca in resp:
251 logger.debug("VCA details: {}".format(yaml.safe_dump(vca)))
252 if long:
253 project_id, project_name = utils.get_project(project_list, vca)
254 detailed_status = vca.get("_admin", {}).get("detailed-status", "-")
255 table.add_row(
256 [
257 vca["name"],
258 vca["_id"],
259 project_name,
260 vca.get("_admin", {}).get("operationalState", "-"),
261 utils.wrap_text(text=detailed_status, width=40),
262 ]
263 )
264 else:
265 table.add_row(
266 [
267 vca["name"],
268 vca["_id"],
269 vca.get("_admin", {}).get("operationalState", "-"),
270 ]
271 )
272 table.align = "l"
273 print(table)
274
275
276 @click.command(name="vca-show", short_help="shows the details of a VCA")
277 @click.argument("name")
278 @click.option("--literal", is_flag=True, help="print literally, no pretty table")
279 @click.pass_context
280 def vca_show(ctx, name, literal):
281 """shows the details of a VCA
282
283 NAME: name or ID of the VCA
284 """
285 logger.debug("")
286 resp = ctx.obj.vca.get(name)
287 if literal:
288 print(yaml.safe_dump(resp, indent=4, default_flow_style=False))
289 return
290 table = PrettyTable(["key", "attribute"])
291 for k, v in list(resp.items()):
292 table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)])
293 table.align = "l"
294 print(table)