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