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 |
1 |
import click |
17 |
1 |
from osmclient.cli_commands import utils |
18 |
1 |
from prettytable import PrettyTable |
19 |
1 |
import yaml |
20 |
1 |
import json |
21 |
1 |
import logging |
22 |
|
|
23 |
1 |
logger = logging.getLogger("osmclient") |
24 |
|
|
25 |
|
|
26 |
1 |
@click.command(name="k8scluster-add", short_help="adds a K8s cluster to OSM") |
27 |
1 |
@click.argument("name") |
28 |
1 |
@click.option( |
29 |
|
"--creds", prompt=True, help="credentials file, i.e. a valid `.kube/config` file" |
30 |
|
) |
31 |
1 |
@click.option("--version", prompt=True, help="Kubernetes version") |
32 |
1 |
@click.option( |
33 |
|
"--vim", prompt=True, help="VIM target, the VIM where the cluster resides" |
34 |
|
) |
35 |
1 |
@click.option( |
36 |
|
"--k8s-nets", |
37 |
|
prompt=True, |
38 |
|
help='''list of VIM networks, in JSON inline format, where the cluster is |
39 |
|
accessible via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''', |
40 |
|
) |
41 |
1 |
@click.option( |
42 |
|
"--init-helm2/--skip-helm2", |
43 |
|
required=False, |
44 |
|
default=True, |
45 |
|
help="Initialize helm v2", |
46 |
|
) |
47 |
1 |
@click.option( |
48 |
|
"--init-helm3/--skip-helm3", |
49 |
|
required=False, |
50 |
|
default=True, |
51 |
|
help="Initialize helm v3", |
52 |
|
) |
53 |
1 |
@click.option( |
54 |
|
"--init-jujubundle/--skip-jujubundle", |
55 |
|
required=False, |
56 |
|
default=True, |
57 |
|
help="Initialize juju-bundle", |
58 |
|
) |
59 |
1 |
@click.option("--description", default=None, help="human readable description") |
60 |
1 |
@click.option( |
61 |
|
"--namespace", |
62 |
|
default="kube-system", |
63 |
|
help="namespace to be used for its operation, defaults to `kube-system`", |
64 |
|
) |
65 |
1 |
@click.option( |
66 |
|
"--wait", |
67 |
|
required=False, |
68 |
|
default=False, |
69 |
|
is_flag=True, |
70 |
|
help="do not return the control immediately, but keep it " |
71 |
|
"until the operation is completed, or timeout", |
72 |
|
) |
73 |
1 |
@click.option( |
74 |
|
"--cni", |
75 |
|
default=None, |
76 |
|
help="list of CNI plugins, in JSON inline format, used in the cluster", |
77 |
|
) |
78 |
|
# @click.option('--skip-init', |
79 |
|
# is_flag=True, |
80 |
|
# help='If set, K8s cluster is assumed to be ready for its use with OSM') |
81 |
1 |
@click.pass_context |
82 |
1 |
def k8scluster_add( |
83 |
|
ctx, |
84 |
|
name, |
85 |
|
creds, |
86 |
|
version, |
87 |
|
vim, |
88 |
|
k8s_nets, |
89 |
|
init_helm2, |
90 |
|
init_helm3, |
91 |
|
init_jujubundle, |
92 |
|
description, |
93 |
|
namespace, |
94 |
|
wait, |
95 |
|
cni, |
96 |
|
): |
97 |
|
"""adds a K8s cluster to OSM |
98 |
|
|
99 |
|
NAME: name of the K8s cluster |
100 |
|
""" |
101 |
0 |
utils.check_client_version(ctx.obj, ctx.command.name) |
102 |
0 |
cluster = {} |
103 |
0 |
cluster["name"] = name |
104 |
0 |
with open(creds, "r") as cf: |
105 |
0 |
cluster["credentials"] = yaml.safe_load(cf.read()) |
106 |
0 |
cluster["k8s_version"] = version |
107 |
0 |
cluster["vim_account"] = vim |
108 |
0 |
cluster["nets"] = yaml.safe_load(k8s_nets) |
109 |
0 |
if not (init_helm2 and init_jujubundle and init_helm3): |
110 |
0 |
cluster["deployment_methods"] = { |
111 |
|
"helm-chart": init_helm2, |
112 |
|
"juju-bundle": init_jujubundle, |
113 |
|
"helm-chart-v3": init_helm3, |
114 |
|
} |
115 |
0 |
if description: |
116 |
0 |
cluster["description"] = description |
117 |
0 |
if namespace: |
118 |
0 |
cluster["namespace"] = namespace |
119 |
0 |
if cni: |
120 |
0 |
cluster["cni"] = yaml.safe_load(cni) |
121 |
0 |
ctx.obj.k8scluster.create(name, cluster, wait) |
122 |
|
|
123 |
|
|
124 |
1 |
@click.command(name="k8scluster-update", short_help="updates a K8s cluster") |
125 |
1 |
@click.argument("name") |
126 |
1 |
@click.option("--newname", help="New name for the K8s cluster") |
127 |
1 |
@click.option("--creds", help="credentials file, i.e. a valid `.kube/config` file") |
128 |
1 |
@click.option("--version", help="Kubernetes version") |
129 |
1 |
@click.option("--vim", help="VIM target, the VIM where the cluster resides") |
130 |
1 |
@click.option( |
131 |
|
"--k8s-nets", |
132 |
|
help='''list of VIM networks, in JSON inline format, where the cluster is accessible |
133 |
|
via L3 routing, e.g. "{(k8s_net1:vim_network1) [,(k8s_net2:vim_network2) ...]}"''', |
134 |
|
) |
135 |
1 |
@click.option("--description", help="human readable description") |
136 |
1 |
@click.option( |
137 |
|
"--namespace", |
138 |
|
help="namespace to be used for its operation, defaults to `kube-system`", |
139 |
|
) |
140 |
1 |
@click.option( |
141 |
|
"--wait", |
142 |
|
required=False, |
143 |
|
default=False, |
144 |
|
is_flag=True, |
145 |
|
help="do not return the control immediately, but keep it " |
146 |
|
"until the operation is completed, or timeout", |
147 |
|
) |
148 |
1 |
@click.option( |
149 |
|
"--cni", help="list of CNI plugins, in JSON inline format, used in the cluster" |
150 |
|
) |
151 |
1 |
@click.pass_context |
152 |
1 |
def k8scluster_update( |
153 |
|
ctx, name, newname, creds, version, vim, k8s_nets, description, namespace, wait, cni |
154 |
|
): |
155 |
|
"""updates a K8s cluster |
156 |
|
|
157 |
|
NAME: name or ID of the K8s cluster |
158 |
|
""" |
159 |
0 |
utils.check_client_version(ctx.obj, ctx.command.name) |
160 |
0 |
cluster = {} |
161 |
0 |
if newname: |
162 |
0 |
cluster["name"] = newname |
163 |
0 |
if creds: |
164 |
0 |
with open(creds, "r") as cf: |
165 |
0 |
cluster["credentials"] = yaml.safe_load(cf.read()) |
166 |
0 |
if version: |
167 |
0 |
cluster["k8s_version"] = version |
168 |
0 |
if vim: |
169 |
0 |
cluster["vim_account"] = vim |
170 |
0 |
if k8s_nets: |
171 |
0 |
cluster["nets"] = yaml.safe_load(k8s_nets) |
172 |
0 |
if description: |
173 |
0 |
cluster["description"] = description |
174 |
0 |
if namespace: |
175 |
0 |
cluster["namespace"] = namespace |
176 |
0 |
if cni: |
177 |
0 |
cluster["cni"] = yaml.safe_load(cni) |
178 |
0 |
ctx.obj.k8scluster.update(name, cluster, wait) |
179 |
|
|
180 |
|
|
181 |
1 |
@click.command(name="k8scluster-delete", short_help="deletes a K8s cluster") |
182 |
1 |
@click.argument("name") |
183 |
1 |
@click.option( |
184 |
|
"--force", is_flag=True, help="forces the deletion from the DB (not recommended)" |
185 |
|
) |
186 |
1 |
@click.option( |
187 |
|
"--wait", |
188 |
|
required=False, |
189 |
|
default=False, |
190 |
|
is_flag=True, |
191 |
|
help="do not return the control immediately, but keep it " |
192 |
|
"until the operation is completed, or timeout", |
193 |
|
) |
194 |
1 |
@click.pass_context |
195 |
1 |
def k8scluster_delete(ctx, name, force, wait): |
196 |
|
"""deletes a K8s cluster |
197 |
|
|
198 |
|
NAME: name or ID of the K8s cluster to be deleted |
199 |
|
""" |
200 |
0 |
utils.check_client_version(ctx.obj, ctx.command.name) |
201 |
0 |
ctx.obj.k8scluster.delete(name, force, wait) |
202 |
|
|
203 |
|
|
204 |
1 |
@click.command(name="k8scluster-list") |
205 |
1 |
@click.option( |
206 |
|
"--filter", |
207 |
|
default=None, |
208 |
|
multiple=True, |
209 |
|
help="restricts the list to the K8s clusters matching the filter", |
210 |
|
) |
211 |
1 |
@click.option("--literal", is_flag=True, help="print literally, no pretty table") |
212 |
1 |
@click.option("--long", is_flag=True, help="get more details") |
213 |
1 |
@click.pass_context |
214 |
1 |
def k8scluster_list(ctx, filter, literal, long): |
215 |
|
"""list all K8s clusters""" |
216 |
0 |
utils.check_client_version(ctx.obj, ctx.command.name) |
217 |
0 |
if filter: |
218 |
0 |
filter = "&".join(filter) |
219 |
0 |
resp = ctx.obj.k8scluster.list(filter) |
220 |
0 |
if literal: |
221 |
0 |
print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) |
222 |
0 |
return |
223 |
0 |
if long: |
224 |
0 |
table = PrettyTable( |
225 |
|
[ |
226 |
|
"Name", |
227 |
|
"Id", |
228 |
|
"Project", |
229 |
|
"Version", |
230 |
|
"VIM", |
231 |
|
"K8s-nets", |
232 |
|
"Deployment methods", |
233 |
|
"Operational State", |
234 |
|
"Op. state (details)", |
235 |
|
"Description", |
236 |
|
"Detailed status", |
237 |
|
] |
238 |
|
) |
239 |
0 |
project_list = ctx.obj.project.list() |
240 |
|
else: |
241 |
0 |
table = PrettyTable( |
242 |
|
["Name", "Id", "VIM", "Operational State", "Op. state details"] |
243 |
|
) |
244 |
0 |
try: |
245 |
0 |
vim_list = ctx.obj.vim.list() |
246 |
0 |
except Exception: |
247 |
0 |
vim_list = [] |
248 |
0 |
for cluster in resp: |
249 |
0 |
logger.debug("Cluster details: {}".format(yaml.safe_dump(cluster))) |
250 |
0 |
vim_name = utils.get_vim_name(vim_list, cluster["vim_account"]) |
251 |
|
# vim_info = '{} ({})'.format(vim_name,cluster['vim_account']) |
252 |
0 |
vim_info = vim_name |
253 |
0 |
op_state_details = "Helm: {}\nJuju: {}".format( |
254 |
|
cluster["_admin"].get("helm-chart", {}).get("operationalState", "-"), |
255 |
|
cluster["_admin"].get("juju-bundle", {}).get("operationalState", "-"), |
256 |
|
) |
257 |
0 |
if long: |
258 |
0 |
project_id, project_name = utils.get_project(project_list, cluster) |
259 |
|
# project_info = '{} ({})'.format(project_name, project_id) |
260 |
0 |
project_info = project_name |
261 |
0 |
detailed_status = cluster["_admin"].get("detailed-status", "-") |
262 |
0 |
table.add_row( |
263 |
|
[ |
264 |
|
cluster["name"], |
265 |
|
cluster["_id"], |
266 |
|
project_info, |
267 |
|
cluster["k8s_version"], |
268 |
|
vim_info, |
269 |
|
json.dumps(cluster["nets"]), |
270 |
|
json.dumps(cluster["deployment_methods"]), |
271 |
|
cluster["_admin"]["operationalState"], |
272 |
|
op_state_details, |
273 |
|
utils.trunc_text(cluster.get("description") or "", 40), |
274 |
|
utils.wrap_text(text=detailed_status, width=40), |
275 |
|
] |
276 |
|
) |
277 |
|
else: |
278 |
0 |
table.add_row( |
279 |
|
[ |
280 |
|
cluster["name"], |
281 |
|
cluster["_id"], |
282 |
|
vim_info, |
283 |
|
cluster["_admin"]["operationalState"], |
284 |
|
op_state_details, |
285 |
|
] |
286 |
|
) |
287 |
0 |
table.align = "l" |
288 |
0 |
print(table) |
289 |
|
|
290 |
|
|
291 |
1 |
@click.command(name="k8scluster-show", short_help="shows the details of a K8s cluster") |
292 |
1 |
@click.argument("name") |
293 |
1 |
@click.option("--literal", is_flag=True, help="print literally, no pretty table") |
294 |
1 |
@click.pass_context |
295 |
1 |
def k8scluster_show(ctx, name, literal): |
296 |
|
"""shows the details of a K8s cluster |
297 |
|
|
298 |
|
NAME: name or ID of the K8s cluster |
299 |
|
""" |
300 |
0 |
resp = ctx.obj.k8scluster.get(name) |
301 |
0 |
if literal: |
302 |
0 |
print(yaml.safe_dump(resp, indent=4, default_flow_style=False)) |
303 |
0 |
return |
304 |
0 |
table = PrettyTable(["key", "attribute"]) |
305 |
0 |
for k, v in list(resp.items()): |
306 |
0 |
table.add_row([k, utils.wrap_text(text=json.dumps(v, indent=2), width=100)]) |
307 |
0 |
table.align = "l" |
308 |
0 |
print(table) |