From 52b2e40d77b5c64bc198c464705194dd9ed6133e Mon Sep 17 00:00:00 2001 From: devopstales <42894256+devopstales@users.noreply.github.com> Date: Tue, 5 Aug 2025 09:35:04 +0200 Subject: [PATCH] fix: 4.0.0 --- src/kubedash/blueprint/cluster.py | 14 +- src/kubedash/blueprint/cluster_permission.py | 30 ++-- src/kubedash/blueprint/dashboard.py | 2 +- src/kubedash/blueprint/network.py | 6 +- src/kubedash/blueprint/other_resources.py | 10 +- src/kubedash/blueprint/security.py | 10 +- src/kubedash/blueprint/settings.py | 29 ++-- src/kubedash/blueprint/storage.py | 10 +- src/kubedash/blueprint/user.py | 8 +- src/kubedash/blueprint/workload.py | 42 +++-- src/kubedash/devspace.yaml | 84 ---------- src/kubedash/lib/custom_jinja2.py | 14 +- src/kubedash/lib/k8s/certificate.py | 6 +- src/kubedash/lib/k8s/crds.py | 1 - src/kubedash/lib/k8s/metrics.py | 20 +-- src/kubedash/lib/k8s/namespace.py | 8 +- src/kubedash/lib/k8s/network.py | 8 +- src/kubedash/lib/k8s/node.py | 2 +- src/kubedash/lib/k8s/other.py | 12 +- src/kubedash/lib/k8s/security.py | 136 ++++++++++++---- src/kubedash/lib/k8s/server.py | 2 +- src/kubedash/lib/k8s/storage.py | 12 +- src/kubedash/lib/k8s/workload.py | 55 +++++-- src/kubedash/plugins/__flux/helm_releases.py | 2 +- src/kubedash/plugins/__flux/kustomizations.py | 2 +- src/kubedash/plugins/__flux/notifications.py | 6 +- src/kubedash/plugins/__flux/sources.py | 10 +- .../__flux/templates/flux_objects.html.j2 | 2 +- .../plugins/__gateway_api/functions.py | 18 +- .../plugins/cert_manager/functions.py | 8 +- .../templates/cert-manager-data.html.j2 | 2 +- .../templates/cert-manager.html.j2 | 2 +- .../plugins/external_loadbalancer/cilium.py | 6 +- .../plugins/external_loadbalancer/metallb.py | 12 +- .../external-loadbalancer-data.html.j2 | 2 +- .../templates/external-loadbalancer.html.j2 | 2 +- src/kubedash/plugins/helm/__init__.py | 15 +- src/kubedash/plugins/helm/functions.py | 154 +++++++++++++++--- .../helm/templates/helm-chart-data.html.j2 | 53 +++--- .../helm/templates/helm-charts.html.j2 | 9 +- .../templates/registry-image-list.html.j2 | 2 +- .../templates/registry-image-tag-data.html.j2 | 2 +- .../templates/registry-image-tag-list.html.j2 | 2 +- .../registry/templates/registry.html.j2 | 2 +- .../cluster-role-binding.html.j2 | 2 +- .../cluster-role-data.html.j2 | 100 +++++++----- .../cluster-permission/cluster-role.html.j2 | 2 +- .../cluster-permission/role-binding.html.j2 | 2 +- .../cluster-permission/role-data.html.j2 | 98 ++++++----- .../templates/cluster-permission/role.html.j2 | 2 +- .../service-account.html.j2 | 2 +- .../templates/cluster/crd-data.html.j2 | 2 +- src/kubedash/templates/cluster/crd.html.j2 | 2 +- .../templates/cluster/namespace-data.html.j2 | 4 +- .../templates/cluster/namespace.html.j2 | 64 ++++---- .../templates/cluster/node-data.html.j2 | 6 +- src/kubedash/templates/cluster/node.html.j2 | 2 +- .../dashboards/cluster-metric.html.j2 | 4 +- .../dashboards/cluster-metric_old.html.j2 | 2 +- .../dashboards/cluster-metric_v2.html.j2 | 2 +- .../templates/dashboards/workload-map.html.j2 | 2 +- .../network/ingress-class-data.html.j2 | 2 +- .../templates/network/ingress-class.html.j2 | 2 +- .../templates/network/ingress-data.html.j2 | 2 +- .../templates/network/ingress.html.j2 | 2 +- .../templates/network/service-data.html.j2 | 2 +- .../templates/network/service.html.j2 | 2 +- .../other-resources/hpa-data.html.j2 | 2 +- .../templates/other-resources/hpa.html.j2 | 2 +- .../other-resources/limit-range-data.html.j2 | 2 +- .../other-resources/limit-range.html.j2 | 2 +- .../pod-disruption-budget-data.html.j2 | 2 +- .../pod-disruption-budget.html.j2 | 2 +- .../priority-class-data.html.j2 | 2 +- .../other-resources/priority-class.html.j2 | 2 +- .../resource-quota-data.html.j2 | 2 +- .../other-resources/resource-quota.html.j2 | 2 +- .../other-resources/vpa-data.html.j2 | 2 +- .../templates/other-resources/vpa.html.j2 | 2 +- .../security/network-policy-data.html.j2 | 2 +- .../templates/security/network-policy.html.j2 | 2 +- .../security/priority-class-data.html.j2 | 2 +- .../templates/security/priority-class.html.j2 | 2 +- .../templates/security/secret-data.html.j2 | 6 +- .../templates/security/secret.html.j2 | 2 +- .../segments/chartjs_snippet.html.j2 | 2 + .../segments/datatable_snippet.html.j2 | 7 + .../templates/segments/functions_snippet.j2 | 2 + .../segments/highlight_snippet.html.j2 | 4 + .../templates/segments/pyvis_snippet.html.j2 | 10 ++ .../templates/segments/socket_snippet.html.j2 | 9 + .../templates/settings/cluster-config.html.j2 | 4 +- .../templates/settings/export.html.j2 | 2 +- .../templates/settings/sso-config.html.j2 | 10 +- .../templates/storage/configmap-data.html.j2 | 6 +- .../templates/storage/configmap.html.j2 | 2 +- .../templates/storage/pv-data.html.j2 | 2 +- src/kubedash/templates/storage/pv.html.j2 | 2 +- .../templates/storage/pvc-data.html.j2 | 2 +- src/kubedash/templates/storage/pvc.html.j2 | 2 +- .../storage/snapshot-class-data.html.j2 | 2 +- .../templates/storage/snapshot-class.html.j2 | 2 +- .../storage/storage-class-data.html.j2 | 2 +- .../templates/storage/storage-class.html.j2 | 2 +- .../templates/storage/volumesnapshot.html.j2 | 2 +- .../users/group-privilege-edit.html.j2 | 14 +- .../templates/users/group-privilege.html.j2 | 2 +- src/kubedash/templates/users/group.html.j2 | 2 +- .../templates/users/privilege-edit.html.j2 | 6 +- .../templates/users/privilege.html.j2 | 2 +- src/kubedash/templates/users/user.html.j2 | 3 +- src/kubedash/templates/users/userinfo.html.j2 | 2 +- .../templates/workload/daemonset-data.html.j2 | 8 +- .../templates/workload/daemonset.html.j2 | 2 +- .../workload/deployment-data.html.j2 | 8 +- .../templates/workload/deployment.html.j2 | 2 +- .../templates/workload/pod-data.html.j2 | 2 +- .../templates/workload/pod-exec.html.j2 | 4 +- .../templates/workload/pod-log.html.j2 | 4 +- src/kubedash/templates/workload/pod.html.j2 | 2 +- .../templates/workload/replicaset.html.j2 | 2 +- .../workload/statefulset-data.html.j2 | 8 +- .../templates/workload/statefulset.html.j2 | 2 +- src/operator/README.md | 6 +- 124 files changed, 784 insertions(+), 557 deletions(-) delete mode 100755 src/kubedash/devspace.yaml create mode 100644 src/kubedash/templates/segments/chartjs_snippet.html.j2 create mode 100644 src/kubedash/templates/segments/datatable_snippet.html.j2 create mode 100644 src/kubedash/templates/segments/functions_snippet.j2 create mode 100644 src/kubedash/templates/segments/highlight_snippet.html.j2 create mode 100644 src/kubedash/templates/segments/pyvis_snippet.html.j2 create mode 100644 src/kubedash/templates/segments/socket_snippet.html.j2 diff --git a/src/kubedash/blueprint/cluster.py b/src/kubedash/blueprint/cluster.py index b0b1d040..6c16c1ac 100644 --- a/src/kubedash/blueprint/cluster.py +++ b/src/kubedash/blueprint/cluster.py @@ -29,7 +29,7 @@ @cluster_bp.route("/namespace", methods=['GET', 'POST']) @login_required -def namespaces(): +def namespace(): selected = None user_token = get_user_token(session) @@ -80,11 +80,11 @@ def namespaces_data(): @login_required def namespaces_create(): if request.method == 'POST': - if request.form.get('ns_select', None): - session['ns_select'] = request.form['namespace'] + if request.form.get('namespace', None): + namespace = request.form['namespace'] user_token = get_user_token(session) - k8sNamespaceCreate(session['user_role'], user_token, session['ns_select']) + k8sNamespaceCreate(session['user_role'], user_token, namespace) return redirect(url_for('.namespace')) else: return redirect(url_for('.namespace')) @@ -93,11 +93,11 @@ def namespaces_create(): @login_required def namespaces_delete(): if request.method == 'POST': - if request.form.get('ns_select', None): - session['ns_select'] = request.form['namespace'] + if request.form.get('namespace', None): + namespace = request.form['namespace'] user_token = get_user_token(session) - k8sNamespaceDelete(session['user_role'], user_token, session['ns_select']) + k8sNamespaceDelete(session['user_role'], namespace) return redirect(url_for('.namespace')) else: return redirect(url_for('.namespace')) diff --git a/src/kubedash/blueprint/cluster_permission.py b/src/kubedash/blueprint/cluster_permission.py index 446dd3e4..a3bb541a 100644 --- a/src/kubedash/blueprint/cluster_permission.py +++ b/src/kubedash/blueprint/cluster_permission.py @@ -1,11 +1,13 @@ +from math import e from flask import (Blueprint, redirect, render_template, request, session, url_for) from flask_login import login_required from lib.helper_functions import get_logger from lib.k8s.namespace import k8sNamespaceListGet -from lib.k8s.security import (k8sClusterRoleBindingListGet, - k8sClusterRoleListGet, k8sRoleBindingListGet, +from lib.k8s.security import (k8sClusterRoleBindingListGet, k8sRoleGet, + k8sClusterRoleListGet, k8sClusterRoleGet, + k8sRoleBindingListGet, k8sRoleListGet, k8sSaListGet) from lib.sso import get_user_token @@ -29,7 +31,8 @@ def service_accounts(): user_token = get_user_token(session) if request.method == 'POST': - session['ns_select'] = request.form.get('ns_select') + if 'ns_select' in request.form: + session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') namespace_list, error = k8sNamespaceListGet(session['user_role'], user_token) @@ -57,7 +60,8 @@ def roles(): user_token = get_user_token(session) if request.method == 'POST': - session['ns_select'] = request.form.get('ns_select') + if 'ns_select' in request.form: + session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') namespace_list, error = k8sNamespaceListGet(session['user_role'], user_token) @@ -77,21 +81,19 @@ def roles(): @login_required def role_data(): if request.method == 'POST': - session['ns_select'] = request.form.get('ns_select') + if 'ns_select' in request.form: + session['ns_select'] = request.form.get('ns_select') r_name = request.form.get('r_name') user_token = get_user_token(session) namespace_list, error = k8sNamespaceListGet(session['user_role'], user_token) - if not error: - roles = k8sRoleListGet(session['user_role'], user_token, session['ns_select']) - else: - roles = list() + role = k8sRoleGet(session['user_role'], user_token, r_name, session['ns_select']) return render_template( 'cluster-permission/role-data.html.j2', namespace_list = namespace_list, - roles = roles, + role = role, r_name = r_name, ) else: @@ -108,7 +110,8 @@ def role_bindings(): user_token = get_user_token(session) if request.method == 'POST': - session['ns_select'] = request.form.get('ns_select') + if 'ns_select' in request.form: + session['ns_select'] = request.form.get('ns_select') selected = request.form.get('rb_name') namespace_list, error = k8sNamespaceListGet(session['user_role'], user_token) @@ -151,12 +154,11 @@ def cluster_role_data(): if request.method == 'POST': cr_name = request.form.get('cr_name') user_token = get_user_token(session) - cluster_roles = k8sClusterRoleListGet(session['user_role'], user_token) - + cluster_role = k8sClusterRoleGet(session['user_role'], user_token, cr_name) return render_template( 'cluster-permission/cluster-role-data.html.j2', - cluster_roles = cluster_roles, + cluster_role = cluster_role, cr_name = cr_name, ) else: diff --git a/src/kubedash/blueprint/dashboard.py b/src/kubedash/blueprint/dashboard.py index 68dc2827..f73d1f13 100644 --- a/src/kubedash/blueprint/dashboard.py +++ b/src/kubedash/blueprint/dashboard.py @@ -74,7 +74,7 @@ def workloads(): span.set_attribute("http.method", request.method) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') if tracer and span.is_recording(): span.set_attribute("namespace.selected", request.form.get('ns_select')) diff --git a/src/kubedash/blueprint/network.py b/src/kubedash/blueprint/network.py index fd8ed8ff..c6e73d3c 100644 --- a/src/kubedash/blueprint/network.py +++ b/src/kubedash/blueprint/network.py @@ -74,7 +74,7 @@ def ingresses(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -123,7 +123,7 @@ def services(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -143,7 +143,7 @@ def services_data(): pod_list = None if request.method == 'POST': service_name = request.form.get('service_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) diff --git a/src/kubedash/blueprint/other_resources.py b/src/kubedash/blueprint/other_resources.py index da49f6a6..e1579268 100644 --- a/src/kubedash/blueprint/other_resources.py +++ b/src/kubedash/blueprint/other_resources.py @@ -30,7 +30,7 @@ def vpa(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -82,7 +82,7 @@ def hpa(): selected = None if request.method == 'POST': - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -135,7 +135,7 @@ def pdp(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -187,7 +187,7 @@ def resource_quota(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -239,7 +239,7 @@ def limit_range(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') diff --git a/src/kubedash/blueprint/security.py b/src/kubedash/blueprint/security.py index a3a53b12..e963743a 100644 --- a/src/kubedash/blueprint/security.py +++ b/src/kubedash/blueprint/security.py @@ -28,7 +28,7 @@ def secrets(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -50,7 +50,7 @@ def secrets(): def secrets_data(): if request.method == 'POST': secret_name = request.form.get('secret_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -84,7 +84,7 @@ def policies_list(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -106,7 +106,7 @@ def policies_list(): def policies_data(): if request.method == 'POST': policy_name = request.form.get('policy_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -154,7 +154,7 @@ def priorityclass_list(): def priorityclass_data(): if request.method == 'POST': pc_name = request.form.get('pc_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) diff --git a/src/kubedash/blueprint/settings.py b/src/kubedash/blueprint/settings.py index 024b8030..bdb55b6f 100644 --- a/src/kubedash/blueprint/settings.py +++ b/src/kubedash/blueprint/settings.py @@ -38,15 +38,26 @@ def sso_config(): if request.method == 'POST': oauth_server_uri = request.form['oauth_server_uri'] - oauth_server_ca = str(base64_encode(oauth_server_ca.strip()), 'UTF-8') if oauth_server_ca else None + oauth_server_ca = None + if "oauth_server_ca" in request.form: + oauth_server_ca_bas64 = request.form['oauth_server_ca'] + oauth_server_ca = str(base64_encode(oauth_server_ca_bas64.strip()), 'UTF-8') client_id = request.form['client_id'] client_secret = request.form['client_secret'] base_uri = request.form['base_uri'] if not base_uri: base_uri = request.root_url.rstrip(request.root_url[-1]) - scope = request.form.getlist('scope') - while("" in scope): - scope.remove("") + if "scope" in request.form: + scope = request.form.getlist('scope') + while("" in scope): + scope.remove("") + else: + scope = [ + "openid", # mandatory for OpenIDConnect auth + "email", # smallest and most consistent scope and claim + "offline_access", # needed to actually ask for refresh_token + "profile", + ] request_type = request.form['request_type'] if request_type == "edit": @@ -71,13 +82,7 @@ def sso_config(): return render_template( 'settings/sso-config.html.j2', base_uri = request.root_url.rstrip(request.root_url[-1]), - scope = [ - "openid", # mandatory for OpenIDConnect auth - "email", # smallest and most consistent scope and claim - "offline_access", # needed to actually ask for refresh_token - "good-service", - "profile", - ] + scope = scope ) else: return render_template( @@ -99,7 +104,7 @@ def callback(): flash('Error encountered.', "danger") ssoServer = SSOSererGet() if ('code' not in request.args and 'state' not in request.args) or not ssoServer: - return redirect(url_for('sso_bp.login')) + return redirect(url_for('sso.login')) else: auth_server_info, oauth = get_auth_server_info() token_url = auth_server_info["token_endpoint"] diff --git a/src/kubedash/blueprint/storage.py b/src/kubedash/blueprint/storage.py index 2fcb93d2..9f26a92e 100644 --- a/src/kubedash/blueprint/storage.py +++ b/src/kubedash/blueprint/storage.py @@ -123,7 +123,7 @@ def pvc(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -179,7 +179,7 @@ def pv(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -202,7 +202,7 @@ def pv(): def pv_data(): pv_data = None if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') user_token = get_user_token(session) @@ -257,7 +257,7 @@ def configmap(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -279,7 +279,7 @@ def configmap(): def configmap_data(): if request.method == 'POST': configmap_name = request.form.get('configmap_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) diff --git a/src/kubedash/blueprint/user.py b/src/kubedash/blueprint/user.py index a2835afe..8bb9471e 100644 --- a/src/kubedash/blueprint/user.py +++ b/src/kubedash/blueprint/user.py @@ -97,11 +97,11 @@ def users_add(): email_test = bool(email_check(email)) if not email_test: flash("Email is not valid", "danger") - return redirect(url_for('users_bp.users_list')) + return redirect(url_for('users.users_list')) elif not len(password) >= 8: flash("Password must be 8 character in length", "danger") - return redirect(url_for('users_bp.users_list')) + return redirect(url_for('users.users_list')) else: if type != "Local": private_key_base64, user_certificate_base64 = k8sCreateUser(username) @@ -109,7 +109,7 @@ def users_add(): UserCreate(username, password, email, type, role, None) flash("User Created Successfully", "success") - return redirect(url_for('users_bp.users_list')) + return redirect(url_for('users.users_list')) else: return redirect(url_for('auth.login')) @@ -120,7 +120,7 @@ def users_delete(): username = request.form['username'] UserDelete(username) flash("User Deleted Successfully", "success") - return redirect(url_for('users_bp.users_list')) + return redirect(url_for('users.users_list')) else: return redirect(url_for('auth.login')) diff --git a/src/kubedash/blueprint/workload.py b/src/kubedash/blueprint/workload.py index e74ec103..4e0ffb04 100644 --- a/src/kubedash/blueprint/workload.py +++ b/src/kubedash/blueprint/workload.py @@ -15,7 +15,7 @@ k8sDaemonSetsGet, k8sDeploymentsGet, k8sDeploymentsPatchReplica, k8sPodExecSocket, k8sPodExecStream, k8sPodGet, k8sPodGetContainers, - k8sPodListGet, k8sPodLogsStream, + k8sPodListGet, k8sPodLogsStream, k8sPodDelete, k8sReplicaSetsGet, k8sStatefulSetPatchReplica, k8sStatefulSetsGet) from lib.sso import get_user_token @@ -50,7 +50,7 @@ def pod_list(): if request.method == 'POST': selected = request.form.get('selected') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -65,13 +65,31 @@ def pod_list(): namespaces = namespace_list, selected = selected ) + +@workload_bp.route('/pods/delete', methods=['POST']) +@login_required +def pod_delete(): + if request.method == 'POST': + pod_name = request.form.get('pod_name') + if 'ns_select' in request.form: + session['ns_select'] = request.form.get('ns_select') + + user_token = get_user_token(session) + + try: + k8sPodDelete(session['user_role'], user_token, session['ns_select'], pod_name) + return redirect(url_for('.pod_list')) + except ApiException: + return redirect(url_for('.pod_list')) + + @workload_bp.route('/pods/data', methods=['GET', 'POST']) @login_required def pod_data(): if request.method == 'POST': po_name = request.form.get('po_name') - if request.form.get('ns_select'): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -99,7 +117,7 @@ def pod_data(): def pod_logs(): if request.method == 'POST': po_name = request.form.get('po_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -145,7 +163,7 @@ def log_message(po_name, container): def pod_exec(): if request.method == 'POST': po_name = request.form.get('po_name') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -212,7 +230,7 @@ def statefulsets(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected', None) @@ -234,7 +252,7 @@ def statefulsets(): def statefulsets_data(): if request.method == 'POST': selected = request.form.get('selected') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -276,7 +294,7 @@ def daemonsets(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -297,7 +315,7 @@ def daemonsets(): @login_required def daemonset_data(): if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -350,7 +368,7 @@ def deployments(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') @@ -372,7 +390,7 @@ def deployments(): def deployment_data(): if request.method == 'POST': selected = request.form.get('selected') - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') user_token = get_user_token(session) @@ -415,7 +433,7 @@ def replicasets(): user_token = get_user_token(session) if request.method == 'POST': - if request.form.get('ns_select', None): + if 'ns_select' in request.form: session['ns_select'] = request.form.get('ns_select') selected = request.form.get('selected') diff --git a/src/kubedash/devspace.yaml b/src/kubedash/devspace.yaml deleted file mode 100755 index b9790c8b..00000000 --- a/src/kubedash/devspace.yaml +++ /dev/null @@ -1,84 +0,0 @@ -version: v2beta1 -name: kubedashgit - -# This is a list of `pipelines` that DevSpace can execute (you can define your own) -pipelines: - # This is the pipeline for the main command: `devspace dev` (or `devspace run-pipeline dev`) - dev: - run: |- - run_dependencies --all # 1. Deploy any projects this project needs (see "dependencies") - ensure_pull_secrets --all # 2. Ensure pull secrets - create_deployments --all # 3. Deploy Helm charts and manifests specfied as "deployments" - start_dev app # 4. Start dev mode "app" (see "dev" section) - # You can run this pipeline via `devspace deploy` (or `devspace run-pipeline deploy`) - deploy: - run: |- - run_dependencies --all # 1. Deploy any projects this project needs (see "dependencies") - ensure_pull_secrets --all # 2. Ensure pull secrets - build_images --all -t $(git describe --always) # 3. Build, tag (git commit hash) and push all images (see "images") - create_deployments --all # 4. Deploy Helm charts and manifests specfied as "deployments" - -# This is a list of `images` that DevSpace can build for this project -# We recommend to skip image building during development (devspace dev) as much as possible -images: - app: - image: devopstales/kubedash:3.1.0 - dockerfile: ../../docker/kubedash/Dockerfile - context: ../../docker/kubedash/ - -# This is a list of `deployments` that DevSpace can create for this project -deployments: - app: - # This deployment uses `helm` but you can also define `kubectl` deployments or kustomizations - helm: - # We are deploying this project with the Helm chart you provided - chart: - name: ../../deploy/charts - # Under `values` we can define the values for this Helm chart used during `helm install/upgrade` - # You may also use `valuesFiles` to load values from files, e.g. valuesFiles: ["values.yaml"] - values: - someChartValue: "" - -# This is a list of `dev` containers that are based on the containers created by your deployments -dev: - app: - # Search for the container that runs this image - imageSelector: devopstales/kubedash:3.1.0 - # Replace the container image with this dev-optimized image (allows to skip image building during development) - devImage: ghcr.io/loft-sh/devspace-containers/python:3-alpine - # Sync files between the local filesystem and the development container - sync: - - path: ./ - # Open a terminal and use the following command to start it - terminal: - command: ./devspace_start.sh - # Inject a lightweight SSH server into the container (so your IDE can connect to the remote dev env) - ssh: - enabled: true - # Make the following commands from my local machine available inside the dev container - proxyCommands: - - command: devspace - - command: kubectl - - command: helm - - gitCredentials: true - # Forward the following ports to be able access your application via localhost - ports: - - port: "8000" - # Open the following URLs once they return an HTTP status code other than 502 or 503 - open: - - url: http://localhost:8000 - -# Use the `commands` section to define repeatable dev workflows for this project -commands: - migrate-db: - command: |- - echo 'This is a cross-platform, shared command that can be used to codify any kind of dev task.' - echo 'Anyone using this project can invoke it via "devspace run migrate-db"' - -# Define dependencies to other projects with a devspace.yaml -# dependencies: -# api: -# git: https://... # Git-based dependencies -# tag: v1.0.0 -# ui: -# path: ./ui # Path-based dependencies (for monorepos) diff --git a/src/kubedash/lib/custom_jinja2.py b/src/kubedash/lib/custom_jinja2.py index eaf80167..3f16ab6b 100644 --- a/src/kubedash/lib/custom_jinja2.py +++ b/src/kubedash/lib/custom_jinja2.py @@ -17,8 +17,11 @@ def j2_b64decode(value: str) -> str: Returns: decoded_value (str): Decoded value """ - decoded_value = str(base64_decode(value), 'UTF-8') - return decoded_value + if value: + decoded_value = str(base64_decode(value), 'UTF-8') + return decoded_value + else: + raise ValueError("Value cannot be None or empty") ############################################################## ## base64 encode @@ -32,8 +35,11 @@ def j2_b64encode(value: str) -> str: Returns: encoded_value (str): Base64 encoded value """ - encoded_value = str(base64_encode(value), 'UTF-8') - return encoded_value + if value: + encoded_value = str(base64_encode(value), 'UTF-8') + return encoded_value + else: + raise ValueError("Value cannot be None or empty") ############################################################## ## split uppercase diff --git a/src/kubedash/lib/k8s/certificate.py b/src/kubedash/lib/k8s/certificate.py index 1ff6661c..9be7e959 100644 --- a/src/kubedash/lib/k8s/certificate.py +++ b/src/kubedash/lib/k8s/certificate.py @@ -52,7 +52,7 @@ def k8sCreateUserCSR(username_role, user_token, username, user_csr_base64): pretty = "true" field_manager = 'KubeDash' try: - api_response = api_instance.create_certificate_signing_request(body, pretty=pretty, field_manager=field_manager, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.create_certificate_signing_request(body, pretty=pretty, field_manager=field_manager, _request_timeout=1) return True, None except ApiException as e: logger.error("Exception when calling CertificatesV1Api->create_certificate_signing_request: %s\n" % e) @@ -102,7 +102,7 @@ def k8sReadUserCSR(username_role, user_token, username): pretty = "true" name = "kubedash-user-"+username try: - api_response = api_instance.read_certificate_signing_request(name, pretty=pretty, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.read_certificate_signing_request(name, pretty=pretty, _request_timeout=1) user_certificate_base64 = api_response.status.certificate return user_certificate_base64 except ApiException as e: @@ -126,7 +126,7 @@ def k8sDeleteUserCSR(username_role, user_token, username): pretty = "true" name = "kubedash-user-"+username try: - api_response = api_instance.delete_certificate_signing_request(name, pretty=pretty, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.delete_certificate_signing_request(name, pretty=pretty, _request_timeout=1) except ApiException as e: logger.error("Exception when calling CertificatesV1Api->delete_certificate_signing_request: %s\n" % e) diff --git a/src/kubedash/lib/k8s/crds.py b/src/kubedash/lib/k8s/crds.py index 2e028f70..3d0471fb 100644 --- a/src/kubedash/lib/k8s/crds.py +++ b/src/kubedash/lib/k8s/crds.py @@ -46,7 +46,6 @@ def get_custom_resources(username_role, user_token): )[0] for resource in resources.get('resources', []): - print(resource) # Debug if '/' not in resource['name']: crd_list.append({ "name": resource['name'], diff --git a/src/kubedash/lib/k8s/metrics.py b/src/kubedash/lib/k8s/metrics.py index 38c146f9..9e6ed557 100644 --- a/src/kubedash/lib/k8s/metrics.py +++ b/src/kubedash/lib/k8s/metrics.py @@ -77,10 +77,10 @@ def k8sGetClusterMetric(): } } try: - node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1, timeout_seconds=1) - pod_list = k8s_client.CoreV1Api().list_pod_for_all_namespaces(_request_timeout=1, timeout_seconds=1) + node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1) + pod_list = k8s_client.CoreV1Api().list_pod_for_all_namespaces(_request_timeout=1) try: - k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1, timeout_seconds=1) + k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1) except Exception as error: k8s_nodes = None flash("Metrics Server is not installed. If you want to see usage date please install Metrics Server.", "warning") @@ -208,10 +208,10 @@ def k8sGetNodeMetric(node_name): k8sClientConfigGet("Admin", None) totalPodAllocatable = float() try: - node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1, timeout_seconds=1) - pod_list = k8s_client.CoreV1Api().list_pod_for_all_namespaces(_request_timeout=1, timeout_seconds=1) + node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1) + pod_list = k8s_client.CoreV1Api().list_pod_for_all_namespaces(_request_timeout=1) try: - k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1, timeout_seconds=1) + k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1) except Exception as error: k8s_nodes = None flash("Metrics Server is not installed. If you want to see usage date please install Metrics Server.", "warning") @@ -301,7 +301,7 @@ def k8sPVCMetric(namespace): node_list = k8sNodesListGet("Admin", None) for mode in node_list: name = mode["name"] - data = k8s_client.CoreV1Api().connect_get_node_proxy_with_path(name, path="stats/summary", _request_timeout=1, timeout_seconds=1) + data = k8s_client.CoreV1Api().connect_get_node_proxy_with_path(name, path="stats/summary", _request_timeout=1) data_json = eval(data) for pod in data_json["pods"]: if 'volume' in pod: @@ -337,7 +337,7 @@ def k8sGetClusterEvents(username_role, user_token): """ k8sClientConfigGet(username_role, user_token) try: - event_list = k8s_client.CoreV1Api().list_event_for_all_namespaces(_request_timeout=1, timeout_seconds=1) + event_list = k8s_client.CoreV1Api().list_event_for_all_namespaces(_request_timeout=1) events = [] for event in event_list.items: if event.type != "Normal": @@ -455,7 +455,7 @@ def getNodeMetrics(): } try: - k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1, timeout_seconds=1) + k8s_nodes = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "nodes", _request_timeout=1) for node in k8s_nodes['items']: node_metric['name'] = node['metadata']['name'] node_metric['cpu'] = float(parse_quantity(node['usage']['cpu'])) @@ -486,7 +486,7 @@ def getPodMetrics(): "storage": "", } try: - k8s_pods = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "pods", _request_timeout=1, timeout_seconds=1) + k8s_pods = k8s_client.CustomObjectsApi().list_cluster_custom_object("metrics.k8s.io", "v1beta1", "pods", _request_timeout=1) for pod in k8s_pods['items']: for container in pod['containers']: pod_metric['name'] = pod['metadata']['name'] diff --git a/src/kubedash/lib/k8s/namespace.py b/src/kubedash/lib/k8s/namespace.py index 1e984ff9..5b0e6564 100644 --- a/src/kubedash/lib/k8s/namespace.py +++ b/src/kubedash/lib/k8s/namespace.py @@ -31,7 +31,7 @@ def k8sListNamespaces(username_role, user_token): span.set_attribute("user.role", username_role) k8sClientConfigGet(username_role, user_token) try: - namespace_list = k8s_client.CoreV1Api().list_namespace(_request_timeout=1, timeout_seconds=1) + namespace_list = k8s_client.CoreV1Api().list_namespace(_request_timeout=1) return namespace_list, None except ApiException as error: if error.status != 404: @@ -47,7 +47,7 @@ def k8sListNamespaces(username_role, user_token): namespace_list = "" return namespace_list, "CannotConnect" -@cache.memoize(timeout=long_cache_time) +#@cache.memoize(timeout=long_cache_time) def k8sNamespaceListGet(username_role, user_token): """Get the list of namespaces @@ -162,7 +162,7 @@ def k8sNamespaceCreate(username_role, user_token, ns_name): ) ) try: - api_response = api_instance.create_namespace(body, pretty=pretty, field_manager=field_manager, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.create_namespace(body, pretty=pretty, field_manager=field_manager, _request_timeout=1) flash("Namespace Created Successfully", "success") except ApiException as error: if error.status != 404: @@ -186,7 +186,7 @@ def k8sNamespaceDelete(username_role, user_token, ns_name): with k8s_client.ApiClient() as api_client: api_instance = k8s_client.CoreV1Api(api_client) try: - api_response = api_instance.delete_namespace(ns_name, pretty=pretty, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.delete_namespace(ns_name, pretty=pretty, _request_timeout=1) flash("Namespace Deleted Successfully", "success") except ApiException as error: if error.status != 404: diff --git a/src/kubedash/lib/k8s/network.py b/src/kubedash/lib/k8s/network.py index 20cb98e5..df92adcf 100644 --- a/src/kubedash/lib/k8s/network.py +++ b/src/kubedash/lib/k8s/network.py @@ -26,7 +26,7 @@ def k8sIngressClassListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) ING_LIST = list() try: - ingress_class_list = k8s_client.NetworkingV1Api().list_ingress_class(_request_timeout=1, timeout_seconds=1) + ingress_class_list = k8s_client.NetworkingV1Api().list_ingress_class(_request_timeout=1) for ic in ingress_class_list.items: ING_INFO = { "name": ic.metadata.name, @@ -68,7 +68,7 @@ def k8sIngressListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) ING_LIST = list() try: - ingress_list = k8s_client.NetworkingV1Api().list_namespaced_ingress(ns, _request_timeout=1, timeout_seconds=1) + ingress_list = k8s_client.NetworkingV1Api().list_namespaced_ingress(ns, _request_timeout=1) for ingress in ingress_list.items: ig = ingress.status.load_balancer.ingress rules = list() @@ -123,7 +123,7 @@ def k8sServiceListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) SERVICE_LIST = list() try: - service_list = k8s_client.CoreV1Api().list_namespaced_service(ns, _request_timeout=1, timeout_seconds=1) + service_list = k8s_client.CoreV1Api().list_namespaced_service(ns, _request_timeout=1) for service in service_list.items: SERVICE_INFO = { "name": service.metadata.name, @@ -173,7 +173,7 @@ def k8sPodSelectorListGet(username_role, user_token, ns, selectors): else: label_selector = label_selector + f"{key}={value}," try: - pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, label_selector=label_selector, _request_timeout=1, timeout_seconds=1) + pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, label_selector=label_selector, _request_timeout=1) for pod in pod_list.items: POD_INFO = { "status": pod.status.phase, diff --git a/src/kubedash/lib/k8s/node.py b/src/kubedash/lib/k8s/node.py index f2dc11ba..12394e5a 100644 --- a/src/kubedash/lib/k8s/node.py +++ b/src/kubedash/lib/k8s/node.py @@ -27,7 +27,7 @@ def k8sListNodes(username_role, user_token): k8sClientConfigGet(username_role, user_token) node_list = list() try: - node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1, timeout_seconds=1) + node_list = k8s_client.CoreV1Api().list_node(_request_timeout=1) return node_list, None except ApiException as error: if error.status != 404: diff --git a/src/kubedash/lib/k8s/other.py b/src/kubedash/lib/k8s/other.py index fdf7eea2..23a9892d 100644 --- a/src/kubedash/lib/k8s/other.py +++ b/src/kubedash/lib/k8s/other.py @@ -73,7 +73,7 @@ def k8sVPAListGet(username_role, user_token, ns_name): version=api_version, # <- updated based on CRD namespace=ns_name, plural="verticalpodautoscalers", - _request_timeout=1, timeout_seconds=1 + _request_timeout=1 ) for vpa in vpas.get("items", []): @@ -121,7 +121,7 @@ def k8sHPAListGet(username_role, user_token, ns_name): k8sClientConfigGet(username_role, user_token) HPA_LIST = list() try: - hpas = k8s_client.AutoscalingV1Api().list_namespaced_horizontal_pod_autoscaler(ns_name, _request_timeout=1, timeout_seconds=1) + hpas = k8s_client.AutoscalingV1Api().list_namespaced_horizontal_pod_autoscaler(ns_name, _request_timeout=1) for hpa in hpas.items: HPA_DATA = { "name": hpa.metadata.name, @@ -164,7 +164,7 @@ def k8sPodDisruptionBudgetListGet(username_role, user_token, ns_name): PDB_LIST = list() k8sClientConfigGet(username_role, user_token) try: - pdbs = k8s_client.PolicyV1Api().list_namespaced_pod_disruption_budget(namespace=ns_name, _request_timeout=1, timeout_seconds=1) + pdbs = k8s_client.PolicyV1Api().list_namespaced_pod_disruption_budget(namespace=ns_name, _request_timeout=1) for pdb in pdbs.items: PDB_DATA = { "name": pdb.metadata.name, @@ -214,7 +214,7 @@ def k8sQuotaListGet(username_role, user_token, ns_name): RQ_LIST = list() k8sClientConfigGet(username_role, user_token) try: - rqs = k8s_client.CoreV1Api().list_namespaced_resource_quota(namespace=ns_name, _request_timeout=1, timeout_seconds=1) + rqs = k8s_client.CoreV1Api().list_namespaced_resource_quota(namespace=ns_name, _request_timeout=1) for rq in rqs.items: PQ_DATA = { "name": rq.metadata.name, @@ -259,7 +259,7 @@ def k8sLimitRangeListGet(username_role, user_token, ns_name): LR_LIST = list() k8sClientConfigGet(username_role, user_token) try: - lrs = k8s_client.CoreV1Api().list_namespaced_limit_range(ns_name, _request_timeout=1, timeout_seconds=1) + lrs = k8s_client.CoreV1Api().list_namespaced_limit_range(ns_name, _request_timeout=1) for lr in lrs.items: LR_DATA = { "name": lr.metadata.name, @@ -299,7 +299,7 @@ def k8sPriorityClassList(username_role, user_token): PC_LIST = list() k8sClientConfigGet(username_role, user_token) - pcs = k8s_client.SchedulingV1Api().list_priority_class(_request_timeout=1, timeout_seconds=1) + pcs = k8s_client.SchedulingV1Api().list_priority_class(_request_timeout=1) for cs in pcs.items: PCS_DATA = { "name": cs.metadata.name, diff --git a/src/kubedash/lib/k8s/security.py b/src/kubedash/lib/k8s/security.py index 653fd788..64c879c7 100644 --- a/src/kubedash/lib/k8s/security.py +++ b/src/kubedash/lib/k8s/security.py @@ -30,7 +30,7 @@ def k8sPodListVulnsGet(username_role, user_token, ns): POD_VULN_LIST = list() HAS_REPORT = False try: - pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1, timeout_seconds=1) + pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get cluster roles - %s" % error.status) @@ -43,7 +43,7 @@ def k8sPodListVulnsGet(username_role, user_token, ns): api_group = "trivy-operator.devopstales.io" api_version = "v1" api_plural = "vulnerabilityreports" - vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1, timeout_seconds=1) + vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1) HAS_REPORT = True except Exception as error: vulnerabilityreport_list = None @@ -56,7 +56,7 @@ def k8sPodListVulnsGet(username_role, user_token, ns): api_group = "aquasecurity.github.io" api_version = "v1alpha1" api_plural = "vulnerabilityreports" - vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1, timeout_seconds=1) + vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1) HAS_REPORT = True except Exception as error2: vulnerabilityreport_list = None @@ -126,7 +126,7 @@ def k8sPodVulnsGet(username_role, user_token, ns, pod): POD_VULNS = {} HAS_REPORT = False try: - pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1, timeout_seconds=1) + pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get cluster roles - %s" % error.status) @@ -140,7 +140,7 @@ def k8sPodVulnsGet(username_role, user_token, ns, pod): api_group = "trivy-operator.devopstales.io" api_version = "v1" api_plural = "vulnerabilityreports" - vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1, timeout_seconds=1) + vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1) except ApiException as error: ##################################################### # aquasecurity trivy operator functions @@ -150,7 +150,7 @@ def k8sPodVulnsGet(username_role, user_token, ns, pod): api_group = "aquasecurity.github.io" api_version = "v1alpha1" api_plural = "vulnerabilityreports" - vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1, timeout_seconds=1) + vulnerabilityreport_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, ns, api_plural, _request_timeout=1) except ApiException as error2: vulnerabilityreport_list = None if error2.status != 404: @@ -243,7 +243,7 @@ def k8sSaListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) SA_LIST = list() try: - service_accounts = k8s_client.CoreV1Api().list_namespaced_service_account(ns, _request_timeout=1, timeout_seconds=1) + service_accounts = k8s_client.CoreV1Api().list_namespaced_service_account(ns, _request_timeout=1) for sa in service_accounts.items: SA_INFO = { "name": sa.metadata.name, @@ -273,6 +273,43 @@ def k8sSaListGet(username_role, user_token, ns): ## Role ############################################################## +@cache.memoize(timeout=long_cache_time) +def k8sRoleGet(username_role, user_token, role_name, ns): + """Get a Role for a given namespace. + + Args: + username_role (str): Role of the current user + user_token (str): Auth token of the current user + role_name (str): Name of the Role + ns (str): Namespace name + + Returns: + ROLE_INFO (dict): Information about the Role + ERROR (str): Error message if any + """ + ROLE_INFO = None + k8sClientConfigGet(username_role, user_token) + try: + role_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role(ns, _request_timeout=1) + for role in role_list.items: + if role.metadata.name == role_name: + ROLE_INFO = { + "name": role.metadata.name, + "annotations": trimAnnotations(role.metadata.annotations), + "labels": role.metadata.labels, + "rules": role.rules, + "created": role.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S'), + } + return ROLE_INFO + except ApiException as error: + if error.status != 404: + ErrorHandler(logger, error, "get roles list - %s" % error.status) + return ROLE_INFO + except Exception as error: + ERROR = "k8sRoleGet: %s" % error + ErrorHandler(logger, "error", ERROR) + return ROLE_INFO + @cache.memoize(timeout=long_cache_time) def k8sRoleListGet(username_role, user_token, ns): """Get a list of Roles for a given namespace. @@ -289,7 +326,7 @@ def k8sRoleListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) ROLE_LIST = list() try: - role_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role(ns, _request_timeout=1, timeout_seconds=1) + role_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role(ns, _request_timeout=1) for role in role_list.items: ROLE_INFO = { "name": role.metadata.name, @@ -329,7 +366,7 @@ def k8sRoleBindingListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) ROLE_BINDING_LIST = list() try: - role_binding_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role_binding(ns, _request_timeout=1, timeout_seconds=1) + role_binding_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role_binding(ns, _request_timeout=1) for rb in role_binding_list.items: ROLE_BINDING_INFO = { "name": rb.metadata.name, @@ -380,7 +417,7 @@ def k8sRoleBindingGet(obeject_name, namespace): pretty = 'true' try: api_response = api_instance.read_namespaced_role_binding( - obeject_name, namespace, pretty=pretty, _request_timeout=1, timeout_seconds=1 + obeject_name, namespace, pretty=pretty, _request_timeout=1 ) return True, None except ApiException as e: @@ -482,7 +519,7 @@ def k8sRoleBindingCreate(user_role, namespace, username, group_name): ) try: api_response = api_instance.create_namespaced_role_binding( - namespace, body, pretty=pretty, field_manager=field_manager, _request_timeout=1, timeout_seconds=1 + namespace, body, pretty=pretty, field_manager=field_manager, _request_timeout=1 ) return True, None except ApiException as e: @@ -524,7 +561,7 @@ def k8sRoleBindingAdd(user_role, username, group_name, user_namespaces, user_all for namespace in namespace_list: is_rolebinding_exists, error = k8sRoleBindingGet(obeject_name, namespace) if error: - ErrorHandler(logger, error, "get RoleBinding %s - %s" % (obeject_name, error.status)) + ErrorHandler(logger, error, "get RoleBinding %s - %s" % (obeject_name, error)) else: if is_rolebinding_exists: ErrorHandler(logger, "CannotConnect", "RoleBinding %s alredy exists in %s namespace" % (obeject_name, namespace)) @@ -553,7 +590,7 @@ def k8sUserClusterRoleTemplateListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) CLUSTER_ROLE_LIST = list() try: - cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1, timeout_seconds=1) + cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1) try: for cr in cluster_roles.items: if "template-cluster-resources---" in cr.metadata.name: @@ -580,7 +617,7 @@ def k8sUserRoleTemplateListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) CLUSTER_ROLE_LIST = list() try: - cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1, timeout_seconds=1) + cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1) try: for cr in cluster_roles.items: if "template-namespaced-resources---" in cr.metadata.name: @@ -600,7 +637,7 @@ def k8sUserRoleTemplateListGet(username_role, user_token): ############################################################## @cache.memoize(timeout=long_cache_time) -def k8sClusterRoleGet(name): +def k8sClusterRoleObjectGet(name): """Get a ClusterRole Args: @@ -615,7 +652,7 @@ def k8sClusterRoleGet(name): api_instance = k8s_client.RbacAuthorizationV1Api(api_client) pretty = 'true' try: - api_response = api_instance.read_cluster_role(name, pretty=pretty, _request_timeout=1, timeout_seconds=1) + api_response = api_instance.read_cluster_role(name, pretty=pretty, _request_timeout=1) return True, None except ApiException as e: if e.status != 404: @@ -644,7 +681,7 @@ def k8sClusterRoleCreate(name, body): field_manager = 'KubeDash' try: api_response = api_instance.create_cluster_role( - body, pretty=pretty, field_manager=field_manager, _request_timeout=1, timeout_seconds=1 + body, pretty=pretty, field_manager=field_manager, _request_timeout=1 ) return True except ApiException as e: @@ -826,7 +863,7 @@ def k8sClusterRolesAdd(): for role in cluster_role_list: name = "template-cluster-resources---" + role - is_clusterrole_exists, error = k8sClusterRoleGet(name) + is_clusterrole_exists, error = k8sClusterRoleObjectGet(name) if error: continue else: @@ -838,7 +875,7 @@ def k8sClusterRolesAdd(): for role in namespaced_role_list: name = "template-namespaced-resources---" + role - is_clusterrole_exists, error = k8sClusterRoleGet(name) + is_clusterrole_exists, error = k8sClusterRoleObjectGet(name) if error: continue else: @@ -848,6 +885,45 @@ def k8sClusterRolesAdd(): k8sClusterRoleCreate(name, roleVars[role]) logger.info("ClusterRole %s created" % name) # WARNING +def k8sClusterRoleGet(username_role, user_token, cluster_role_name=None): + """Get Cluster Roles from Kubernetes API + + Args: + username_role (str): Role of the current user + user_token (str): Auth token of the current user + cluster_role_name (str, optional): Name of the Cluster Role to get. Defaults to None. + + Returns: + CLUSTER_ROLE (list): Cluster Roles + error (str): Error message if any + """ + k8sClientConfigGet(username_role, user_token) + CLUSTER_ROLE_DATA = None + try: + cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1) + try: + for cr in cluster_roles.items: + if cluster_role_name is not None: + if cr.metadata.name == cluster_role_name: + CLUSTER_ROLE_DATA = { + "name": cr.metadata.name, + "annotations": trimAnnotations(cr.metadata.annotations), + "labels": cr.metadata.labels, + "rules": cr.rules, + "created": cr.metadata.creation_timestamp.strftime('%Y-%m-%d %H:%M:%S'), + } + return CLUSTER_ROLE_DATA + except: + return CLUSTER_ROLE_DATA + except ApiException as error: + if error.status != 404: + ErrorHandler(logger, error, "get cluster role %s - %s" % (cluster_role_name, error.status)) + return CLUSTER_ROLE_DATA + except Exception as error: + ERROR = "k8sClusterRoleObjectGet: %s" % error + ErrorHandler(logger, "error", ERROR) + return CLUSTER_ROLE_DATA + @cache.memoize(timeout=long_cache_time) def k8sClusterRoleListGet(username_role, user_token): """ @@ -876,7 +952,7 @@ def k8sClusterRoleListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) CLUSTER_ROLE_LIST = list() try: - cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1, timeout_seconds=1) + cluster_roles = k8s_client.RbacAuthorizationV1Api().list_cluster_role(_request_timeout=1) try: for cr in cluster_roles.items: CLUSTER_ROLE_DATA = { @@ -934,7 +1010,7 @@ def k8sClusterRoleBindingListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) CLUSTER_ROLE_BINDING_LIST = [] try: - cluster_role_bindings = k8s_client.RbacAuthorizationV1Api().list_cluster_role_binding(_request_timeout=1, timeout_seconds=1) + cluster_role_bindings = k8s_client.RbacAuthorizationV1Api().list_cluster_role_binding(_request_timeout=1) for crb in cluster_role_bindings.items: CLUSTER_ROLE_BINDING_INFO = { "name": crb.metadata.name, @@ -977,7 +1053,7 @@ def k8sClusterRoleBindingGet(obeject_name): pretty = 'true' try: api_response = api_instance.read_cluster_role_binding( - obeject_name, pretty=pretty, _request_timeout=1, timeout_seconds=1 + obeject_name, pretty=pretty, _request_timeout=1 ) return True, None except ApiException as e: @@ -1047,7 +1123,7 @@ def k8sClusterRoleBindingCreate(user_cluster_role, username, group_name): ) try: pi_response = api_instance.create_cluster_role_binding( - body, pretty=pretty, field_manager=field_manager, _request_timeout=1, timeout_seconds=1 + body, pretty=pretty, field_manager=field_manager, _request_timeout=1 ) flash("User Role Created Successfully", "success") except ApiException as e: @@ -1069,7 +1145,7 @@ def k8sClusterRoleBindingAdd(user_cluster_role, username, group_name): is_clusterrolebinding_exists, error = k8sClusterRoleBindingGet(obeject_name) if error: - ErrorHandler(logger, error, "get ClusterRoleBinding %s - %s" % (obeject_name, error.status)) + ErrorHandler(logger, error, "get ClusterRoleBinding %s - %s" % (obeject_name, error)) else: if is_clusterrolebinding_exists: ErrorHandler(logger, "CannotConnect", "ClusterRoleBinding %s alredy exists" % obeject_name) @@ -1093,7 +1169,7 @@ def k8sUserPriviligeList(username_role="Admin", user_token=None, user="admin"): namespaces, error = k8sNamespaceListGet(username_role, user_token) if not error: for ns in namespaces: - role_binding_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role_binding(ns, _request_timeout=1, timeout_seconds=1) + role_binding_list = k8s_client.RbacAuthorizationV1Api().list_namespaced_role_binding(ns, _request_timeout=1) for rb in role_binding_list.items: for obj in rb.subjects: if obj.kind == "User" and obj.name == user: @@ -1102,7 +1178,7 @@ def k8sUserPriviligeList(username_role="Admin", user_token=None, user="admin"): elif rb.role_ref.kind == "Role": ROLE_LIST.append([ns, rb.role_ref.name]) - cluster_role_bindings = k8s_client.RbacAuthorizationV1Api().list_cluster_role_binding(_request_timeout=1, timeout_seconds=1) + cluster_role_bindings = k8s_client.RbacAuthorizationV1Api().list_cluster_role_binding(_request_timeout=1) for crb in cluster_role_bindings.items: if crb.subjects: for obj in crb.subjects: @@ -1114,7 +1190,7 @@ def k8sUserPriviligeList(username_role="Admin", user_token=None, user="admin"): api_instance = k8s_client.RbacAuthorizationV1Api(api_client) pretty = 'true' try: - ROLE = api_instance.read_namespaced_role(r[1], r[0], pretty=pretty, _request_timeout=1, timeout_seconds=1) + ROLE = api_instance.read_namespaced_role(r[1], r[0], pretty=pretty, _request_timeout=1) for rr in ROLE.rules: USER_ROLES.append({r[1]: rr}) except: @@ -1125,7 +1201,7 @@ def k8sUserPriviligeList(username_role="Admin", user_token=None, user="admin"): api_instance = k8s_client.RbacAuthorizationV1Api(api_client) pretty = 'true' try: - CLUSTER_ROLE = api_instance.read_cluster_role(cr, pretty=pretty, _request_timeout=1, timeout_seconds=1) + CLUSTER_ROLE = api_instance.read_cluster_role(cr, pretty=pretty, _request_timeout=1) for crr in CLUSTER_ROLE.rules: USER_CLUSTER_ROLES.append(crr) except Exception as error: @@ -1141,7 +1217,7 @@ def k8sUserPriviligeList(username_role="Admin", user_token=None, user="admin"): def k8sSecretListGet(username_role, user_token, namespace): k8sClientConfigGet(username_role, user_token) SECRET_LIST = list() - secret_list = k8s_client.CoreV1Api().list_namespaced_secret(namespace, _request_timeout=1, timeout_seconds=1) + secret_list = k8s_client.CoreV1Api().list_namespaced_secret(namespace, _request_timeout=1) for secret in secret_list.items: SECRET_DATA = { "name": secret.metadata.name, @@ -1164,7 +1240,7 @@ def k8sSecretListGet(username_role, user_token, namespace): def k8sPolicyListGet(username_role, user_token, ns_name): POLICY_LIST = list() k8sClientConfigGet(username_role, user_token) - policy_list = k8s_client.NetworkingV1Api().list_namespaced_network_policy(ns_name, _request_timeout=1, timeout_seconds=1) + policy_list = k8s_client.NetworkingV1Api().list_namespaced_network_policy(ns_name, _request_timeout=1) try: for policy in policy_list.items: POLICY_DATA = { diff --git a/src/kubedash/lib/k8s/server.py b/src/kubedash/lib/k8s/server.py index 792660f4..9efe53fd 100644 --- a/src/kubedash/lib/k8s/server.py +++ b/src/kubedash/lib/k8s/server.py @@ -106,7 +106,7 @@ def k8sGetClusterStatus(username_role="Admin", user_token=None): k8sClientConfigGet(username_role, user_token) try: api = k8s_client.CoreV1Api() - component_statuses = api.list_component_status(_request_timeout=1, timeout_seconds=1) + component_statuses = api.list_component_status(_request_timeout=1) return True diff --git a/src/kubedash/lib/k8s/storage.py b/src/kubedash/lib/k8s/storage.py index bc23f286..4c4cb6b3 100644 --- a/src/kubedash/lib/k8s/storage.py +++ b/src/kubedash/lib/k8s/storage.py @@ -16,7 +16,7 @@ def k8sStorageClassListGet(username_role, user_token): k8sClientConfigGet(username_role, user_token) SC_LIST = list() try: - storage_classes = k8s_client.StorageV1Api().list_storage_class(_request_timeout=1, timeout_seconds=1) + storage_classes = k8s_client.StorageV1Api().list_storage_class(_request_timeout=1) for sc in storage_classes.to_dict()["items"]: SC = { "name": sc["metadata"]["name"], @@ -51,7 +51,7 @@ def k8sSnapshotClassListGet(username_role, user_token): "snapshot.storage.k8s.io", "v1", "volumesnapshotclasses", - _request_timeout=1, timeout_seconds=1 + _request_timeout=1 ) for sc in snapshot_classes["items"]: SC = { @@ -84,7 +84,7 @@ def k8sPersistentVolumeClaimListGet(username_role, user_token, namespace): k8sClientConfigGet(username_role, user_token) PVC_LIST = list() try: - persistent_volume_clames= k8s_client.CoreV1Api().list_namespaced_persistent_volume_claim(namespace, _request_timeout=1, timeout_seconds=1) + persistent_volume_clames= k8s_client.CoreV1Api().list_namespaced_persistent_volume_claim(namespace, _request_timeout=1) for pvc in persistent_volume_clames.items: PVC = { "status": pvc.status.phase, @@ -117,7 +117,7 @@ def k8sPersistentVolumeListGet(username_role, user_token, namespace): k8sClientConfigGet(username_role, user_token) PV_LIST = list() try: - pv_list = k8s_client.CoreV1Api().list_persistent_volume(_request_timeout=1, timeout_seconds=1) + pv_list = k8s_client.CoreV1Api().list_persistent_volume(_request_timeout=1) for pv in pv_list.items: if namespace == pv.spec.claim_ref.namespace: PV = { @@ -167,7 +167,7 @@ def k8sPersistentVolumeSnapshotListGet(username_role, user_token): "snapshot.storage.k8s.io", "v1", "volumesnapshots", - _request_timeout=1, timeout_seconds=1 + _request_timeout=1 ) for pvs in snapshot_list["items"]: PVS = { @@ -200,7 +200,7 @@ def k8sPersistentVolumeSnapshotListGet(username_role, user_token): def k8sConfigmapListGet(username_role, user_token, namespace): k8sClientConfigGet(username_role, user_token) CONFIGMAP_LIST = list() - configmap_list = k8s_client.CoreV1Api().list_namespaced_config_map(namespace, _request_timeout=1, timeout_seconds=1) + configmap_list = k8s_client.CoreV1Api().list_namespaced_config_map(namespace, _request_timeout=1) for configmap in configmap_list.items: CONFIGMAP_DATA = { "name": configmap.metadata.name, diff --git a/src/kubedash/lib/k8s/workload.py b/src/kubedash/lib/k8s/workload.py index 9d2d4e9b..9acba79a 100644 --- a/src/kubedash/lib/k8s/workload.py +++ b/src/kubedash/lib/k8s/workload.py @@ -20,7 +20,7 @@ def k8sDaemonSetsGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) DAEMONSET_LIST = list() try: - daemonset_list = k8s_client.AppsV1Api().list_namespaced_daemon_set(ns, _request_timeout=1, timeout_seconds=1) + daemonset_list = k8s_client.AppsV1Api().list_namespaced_daemon_set(ns, _request_timeout=1) for ds in daemonset_list.items: DAEMONSET_DATA = { "name": ds.metadata.name, @@ -130,7 +130,7 @@ def k8sDaemonsetPatch(username_role, user_token, ns, name, body): k8sClientConfigGet(username_role, user_token) try: api_response = k8s_client.AppsV1Api().patch_namespaced_daemon_set( - name, ns, body, _request_timeout=1, timeout_seconds=1 + name, ns, body, _request_timeout=1 ) flash("Daemonset: %s patched to replicas" % name, "success") logger.info("Deployment: %s patched to replicas" % name) @@ -152,7 +152,7 @@ def k8sDeploymentsGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) DEPLOYMENT_LIST = list() try: - deployment_list = k8s_client.AppsV1Api().list_namespaced_deployment(ns, _request_timeout=1, timeout_seconds=1) + deployment_list = k8s_client.AppsV1Api().list_namespaced_deployment(ns, _request_timeout=1) for d in deployment_list.items: DEPLOYMENT_DATA = { "name": d.metadata.name, @@ -272,7 +272,7 @@ def k8sDeploymentsPatchReplica(username_role, user_token, ns, name, replicas): } ] api_response = k8s_client.AppsV1Api().patch_namespaced_deployment_scale( - name, ns, body, _request_timeout=1, timeout_seconds=1 + name, ns, body, _request_timeout=1 ) flash("Deployment: %s patched to replicas %s" % (name, replicas), "success") logger.info("Deployment: %s patched to replicas %s" % (name, replicas)) @@ -296,7 +296,7 @@ def k8sDeploymentsPatchAnnotation(username_role, user_token, ns, name, replicas) } ] api_response = k8s_client.AppsV1Api().patch_namespaced_deployment( - name, ns, body, _request_timeout=1, timeout_seconds=1 + name, ns, body, _request_timeout=1 ) flash("Deployment: %s Annotation patched" % name, "success") logger.info("Deployment: %s Annotation patched" % name) @@ -318,7 +318,7 @@ def k8sPodListGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) POD_LIST = list() try: - pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1, timeout_seconds=1) + pod_list = k8s_client.CoreV1Api().list_namespaced_pod(ns, _request_timeout=1) for pod in pod_list.items: POD_SUM = { "name": pod.metadata.name, @@ -350,7 +350,7 @@ def k8sPodGet(username_role, user_token, ns, po): k8sClientConfigGet(username_role, user_token) POD_DATA = {} try: - pod_data = k8s_client.CoreV1Api().read_namespaced_pod(po, ns, _request_timeout=1, timeout_seconds=1) + pod_data = k8s_client.CoreV1Api().read_namespaced_pod(po, ns, _request_timeout=1) POD_DATA = { # main "name": po, @@ -490,7 +490,7 @@ def k8sPodGetContainers(username_role, user_token, namespace, pod_name): POD_CONTAINER_LIST = list() POD_INIT_CONTAINER_LIST = list() try: - pod_data = k8s_client.CoreV1Api().read_namespaced_pod(pod_name, namespace, _request_timeout=1, timeout_seconds=1) + pod_data = k8s_client.CoreV1Api().read_namespaced_pod(pod_name, namespace, _request_timeout=1) for c in pod_data.spec.containers: for cs in pod_data.status.container_statuses: if cs.name == c.name: @@ -512,6 +512,33 @@ def k8sPodGetContainers(username_role, user_token, namespace, pod_name): ErrorHandler(logger, "error", ERROR) return POD_CONTAINER_LIST, POD_INIT_CONTAINER_LIST +def k8sPodDelete(username_role, user_token, ns, po): + """ Deletes a pod in the specified namespace. + + Args: + username_role (str): The username and role of the user. + user_token (str): The authentication token for the user. + ns (str): The namespace where the pod is located. + po (str): The name of the pod to delete. + + Returns: + bool: True if the pod was successfully deleted, False otherwise. + """ + k8sClientConfigGet(username_role, user_token) + try: + api_response = k8s_client.CoreV1Api().delete_namespaced_pod( + po, ns, _request_timeout=1 + ) + flash("Pod: %s deleted" % po, "success") + logger.info("Pod: %s deleted" % po) + return True + except ApiException as error: + ErrorHandler(logger, error, "ERROR: %s delete Pod: %s" % (po, error)) + return False + except Exception as error: + ERROR = "k8sPodDelete: %s" % error + ErrorHandler(logger, "error", ERROR) + return False ############################################################## ## Pod Logs @@ -527,7 +554,7 @@ def k8sPodLogsStream(username_role, user_token, namespace, pod_name, container): namespace=namespace, container=container, tail_lines=100, - _request_timeout=1, timeout_seconds=1 + _request_timeout=1 ): socketio.emit('response', {'data': str(line)}, namespace="/log") @@ -552,7 +579,7 @@ def k8sPodExecSocket(username_role, user_token, namespace, pod_name, container): stderr=True, stdin=True, stdout=True, tty=True, _preload_content=False, - _request_timeout=1, timeout_seconds=1 + _request_timeout=1 ) return wsclient except Exception as error: @@ -624,7 +651,7 @@ def k8sReplicaSetsGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) REPLICASET_LIST = list() try: - replicaset_list = k8s_client.AppsV1Api().list_namespaced_replica_set(ns, _request_timeout=1, timeout_seconds=1) + replicaset_list = k8s_client.AppsV1Api().list_namespaced_replica_set(ns, _request_timeout=1) for rs in replicaset_list.items: REPLICASET_DATA = { "name": rs.metadata.name, @@ -668,7 +695,7 @@ def k8sStatefulSetsGet(username_role, user_token, ns): k8sClientConfigGet(username_role, user_token) STATEFULSET_LIST = list() try: - statefulset_list = k8s_client.AppsV1Api().list_namespaced_stateful_set(ns, _request_timeout=1, timeout_seconds=1) + statefulset_list = k8s_client.AppsV1Api().list_namespaced_stateful_set(ns, _request_timeout=1) for sfs in statefulset_list.items: STATEFULSET_DATA = { "name": sfs.metadata.name, @@ -786,7 +813,7 @@ def k8sStatefulSetPatchReplica(username_role, user_token, ns, name, replicas): } ] api_response = k8s_client.AppsV1Api().patch_namespaced_stateful_set_scale( - name, ns, body, _request_timeout=1, timeout_seconds=1 + name, ns, body, _request_timeout=1 ) flash("StatefulSet: %s patched to replicas %s" % (name, replicas), "success") logger.info("StatefulSet: %s patched to replicas %s" % (name, replicas)) @@ -810,7 +837,7 @@ def k8sStatefulSetPatchAnnotation(username_role, user_token, ns, name, replicas) } ] api_response = k8s_client.AppsV1Api().patch_namespaced_stateful_set( - name, ns, body, _request_timeout=1, timeout_seconds=1 + name, ns, body, _request_timeout=1 ) flash("StatefulSet: %s Annotation patched" % name, "success") logger.info("StatefulSet: %s Annotation patched" % name) diff --git a/src/kubedash/plugins/__flux/helm_releases.py b/src/kubedash/plugins/__flux/helm_releases.py index a6553a17..b0b9b6c8 100644 --- a/src/kubedash/plugins/__flux/helm_releases.py +++ b/src/kubedash/plugins/__flux/helm_releases.py @@ -20,7 +20,7 @@ def FluxHelmReleaseGet(username_role, user_token, namespace): api_plural = "helmreleases" k8s_objects = [] try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: diff --git a/src/kubedash/plugins/__flux/kustomizations.py b/src/kubedash/plugins/__flux/kustomizations.py index 1e9e4d5e..c27f5360 100644 --- a/src/kubedash/plugins/__flux/kustomizations.py +++ b/src/kubedash/plugins/__flux/kustomizations.py @@ -20,7 +20,7 @@ def FluxKustomizationGet(username_role, user_token, namespace): api_plural = "kustomizations" k8s_objects = [] try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: diff --git a/src/kubedash/plugins/__flux/notifications.py b/src/kubedash/plugins/__flux/notifications.py index 7ae4a62e..e5f6bfd5 100644 --- a/src/kubedash/plugins/__flux/notifications.py +++ b/src/kubedash/plugins/__flux/notifications.py @@ -19,7 +19,7 @@ def FluxAlertNotificationGet(username_role, user_token, namespace): api_version = notificationVersion api_plural = "alerts" try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: @@ -40,7 +40,7 @@ def FluxProviderNotificationGet(username_role, user_token, namespace): api_plural = "providers" k8s_object_list = list() try: - k8s_object_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_object_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_object_list.get('items', []) except ApiException as error: if error.status != 404: @@ -61,7 +61,7 @@ def FluxReceiverNotificationGet(username_role, user_token, namespace): api_plural = "receivers" k8s_object_list = list() try: - k8s_object_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_object_list = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_object_list.get('items', []) except ApiException as error: if error.status != 404: diff --git a/src/kubedash/plugins/__flux/sources.py b/src/kubedash/plugins/__flux/sources.py index 9c85e44f..e5db29cf 100644 --- a/src/kubedash/plugins/__flux/sources.py +++ b/src/kubedash/plugins/__flux/sources.py @@ -20,7 +20,7 @@ def FluxBucketRepositoryGet(username_role, user_token, namespace): api_version = sourceVersion api_plural = "buckets" try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: @@ -40,7 +40,7 @@ def FluxGitRepositoryGet(username_role, user_token, namespace): api_version = sourceVersion api_plural = "gitrepositories" try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: @@ -60,7 +60,7 @@ def FluxHelmChartGet(username_role, user_token, namespace): api_version = sourceVersion api_plural = "helmcharts" try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: @@ -80,7 +80,7 @@ def FluxHelmRepositoryGet(username_role, user_token, namespace): api_version = sourceVersion api_plural = "helmrepositories" try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: @@ -101,7 +101,7 @@ def FluxOCIRepositoryGet(username_role, user_token, namespace): api_plural = "ocirepositories" k8s_objects = [] try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) return k8s_objects.get('items', []) except ApiException as error: if error.status != 404: diff --git a/src/kubedash/plugins/__flux/templates/flux_objects.html.j2 b/src/kubedash/plugins/__flux/templates/flux_objects.html.j2 index cd89435f..93a94c4c 100644 --- a/src/kubedash/plugins/__flux/templates/flux_objects.html.j2 +++ b/src/kubedash/plugins/__flux/templates/flux_objects.html.j2 @@ -128,6 +128,6 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/plugins/__gateway_api/functions.py b/src/kubedash/plugins/__gateway_api/functions.py index aaf1a4c1..87b4f4a3 100644 --- a/src/kubedash/plugins/__gateway_api/functions.py +++ b/src/kubedash/plugins/__gateway_api/functions.py @@ -20,7 +20,7 @@ def GatewayApiGetBackendTLSPolicy(username_role, user_token, namespace): api_plural = "backendtlspolicies" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) @@ -35,7 +35,7 @@ def GatewayApiGetGatewayClass(username_role, user_token): api_plural = "gatewayclasses" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "name": k8s_object['metadata']['name'], @@ -60,7 +60,7 @@ def GatewayApiGetGateway(username_role, user_token, namespace): api_plural = "gateways" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "name": k8s_object['metadata']['name'], @@ -87,7 +87,7 @@ def GatewayApiGetHTTPRoute(username_role, user_token, namespace): api_plural = "httproutes" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "name": k8s_object['metadata']['name'], @@ -116,7 +116,7 @@ def GatewayApiGetReferenceGrant(username_role, user_token, namespace): api_plural = "referencegrants" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) @@ -131,7 +131,7 @@ def GatewayApiGetGRPCRoute(username_role, user_token, namespace): api_plural = "grpcroute" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) @@ -146,7 +146,7 @@ def GatewayApiGetTCPRoute(username_role, user_token, namespace): api_plural = "tcproutes" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) @@ -161,7 +161,7 @@ def GatewayApiGetTLSRoute(username_role, user_token, namespace): api_plural = "tlsroutes" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) @@ -176,7 +176,7 @@ def GatewayApiGetUDPRoute(username_role, user_token, namespace): api_plural = "udproutes" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) except ApiException as error: if error.status != 404: ErrorHandler(logger, error, "get %s" % api_plural) diff --git a/src/kubedash/plugins/cert_manager/functions.py b/src/kubedash/plugins/cert_manager/functions.py index abbecca2..7dc2a52e 100644 --- a/src/kubedash/plugins/cert_manager/functions.py +++ b/src/kubedash/plugins/cert_manager/functions.py @@ -22,7 +22,7 @@ def IssuerGet(username_role, user_token, namespace): api_plural = "issuers" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) k8s_object_list = GenerateIssuerData(k8s_objects, k8s_object_list) return k8s_object_list except ApiException as error: @@ -41,7 +41,7 @@ def ClusterIssuerGet(username_role, user_token): api_plural = "clusterissuers" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1) k8s_object_list = GenerateIssuerData(k8s_objects, k8s_object_list) return k8s_object_list except ApiException as error: @@ -60,7 +60,7 @@ def CertificateRequestsGet(username_role, user_token, namespace): api_plural = "certificaterequests" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "name": k8s_object['metadata']['name'], @@ -91,7 +91,7 @@ def CertificatesGet(username_role, user_token, namespace): api_plural = "certificates" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "name": k8s_object['metadata']['name'], diff --git a/src/kubedash/plugins/cert_manager/templates/cert-manager-data.html.j2 b/src/kubedash/plugins/cert_manager/templates/cert-manager-data.html.j2 index 7a694c65..bf667666 100644 --- a/src/kubedash/plugins/cert_manager/templates/cert-manager-data.html.j2 +++ b/src/kubedash/plugins/cert_manager/templates/cert-manager-data.html.j2 @@ -154,7 +154,7 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} {% block tail_js %} diff --git a/src/kubedash/plugins/cert_manager/templates/cert-manager.html.j2 b/src/kubedash/plugins/cert_manager/templates/cert-manager.html.j2 index af8e7219..e71f937a 100644 --- a/src/kubedash/plugins/cert_manager/templates/cert-manager.html.j2 +++ b/src/kubedash/plugins/cert_manager/templates/cert-manager.html.j2 @@ -234,7 +234,7 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} {% block tail_js %} diff --git a/src/kubedash/plugins/external_loadbalancer/cilium.py b/src/kubedash/plugins/external_loadbalancer/cilium.py index 1a1a927d..2034fb74 100644 --- a/src/kubedash/plugins/external_loadbalancer/cilium.py +++ b/src/kubedash/plugins/external_loadbalancer/cilium.py @@ -21,7 +21,7 @@ def ciliumloadbalancerippoolsGet(namespace): k8s_object_list = list() k8s_object_error = None #try: - k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "cilium", @@ -66,7 +66,7 @@ def ciliuml2announcementpoliciesGet(namespace): k8s_object_list = list() k8s_object_error = None try: - k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "cilium", @@ -104,7 +104,7 @@ def ciliumbgppeeringpoliciesGet(namespace): k8s_object_list = list() k8s_object_error = None try: - k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_cluster_custom_object(api_group, api_version, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "cilium", diff --git a/src/kubedash/plugins/external_loadbalancer/metallb.py b/src/kubedash/plugins/external_loadbalancer/metallb.py index 113de3f1..0d97c72c 100644 --- a/src/kubedash/plugins/external_loadbalancer/metallb.py +++ b/src/kubedash/plugins/external_loadbalancer/metallb.py @@ -21,7 +21,7 @@ def ipaddresspoolsGet(namespace): k8s_object_list = list() k8s_object_error = None try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", @@ -60,7 +60,7 @@ def l2advertisementsGet(namespace): k8s_object_list = list() k8s_object_error = False try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", @@ -94,7 +94,7 @@ def communitiesGet(namespace): api_plural = "communities" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", @@ -121,7 +121,7 @@ def bgppeersGet(namespace): api_plural = "bgppeers" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", @@ -178,7 +178,7 @@ def bgpadvertisementsGet(namespace): k8s_object_list = list() k8s_object_error = None try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", @@ -221,7 +221,7 @@ def bfdprofilesGet(username_role, user_token, namespace): api_plural = "bfdprofiles" k8s_object_list = list() try: - k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1, timeout_seconds=1) + k8s_objects = k8s_client.CustomObjectsApi().list_namespaced_custom_object(api_group, api_version, namespace, api_plural, _request_timeout=1) for k8s_object in k8s_objects['items']: k8s_object_data = { "type": "metallb", diff --git a/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer-data.html.j2 b/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer-data.html.j2 index 975c27a1..bb04aef6 100644 --- a/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer-data.html.j2 +++ b/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer-data.html.j2 @@ -310,7 +310,7 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} {% block tail_js %} diff --git a/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer.html.j2 b/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer.html.j2 index 77ca3156..302f6c56 100644 --- a/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer.html.j2 +++ b/src/kubedash/plugins/external_loadbalancer/templates/external-loadbalancer.html.j2 @@ -215,7 +215,7 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} {% block tail_js %} diff --git a/src/kubedash/plugins/helm/__init__.py b/src/kubedash/plugins/helm/__init__.py index 4a486c2d..6406f3f3 100644 --- a/src/kubedash/plugins/helm/__init__.py +++ b/src/kubedash/plugins/helm/__init__.py @@ -54,16 +54,21 @@ def charts(): @login_required def charts_data(): if request.method == 'POST': - selected = request.form.get('selected') + helm_release_name = request.form.get('helm_release_name') + helm_release_version = request.form.get('helm_release_version') user_token = get_user_token(session) - has_chart, chart_list = k8sHelmChartListGet(session['user_role'], user_token, session['ns_select']) - if has_chart: - chart_name, chart_data = k8sHelmChartReleaseGet(chart_list) + chart_data = k8sHelmChartReleaseGet( + session['user_role'], + user_token, + session['ns_select'], + helm_release_name, + helm_release_version + ) return render_template( 'helm-chart-data.html.j2', - chart_name = chart_name, + chart_name = helm_release_name, chart_data = chart_data, ) else: diff --git a/src/kubedash/plugins/helm/functions.py b/src/kubedash/plugins/helm/functions.py index 5af1e190..130d8051 100644 --- a/src/kubedash/plugins/helm/functions.py +++ b/src/kubedash/plugins/helm/functions.py @@ -17,18 +17,51 @@ ## Helm Charts functions ############################################################## +def decode_secret_date(secret_data): + secret = None + try: + # Decode the base64 encoded release data + base64_secret_data = str(base64_decode(secret_data.data['release']), 'UTF-8') + secret = json.loads(zlib.decompress(base64_decode(base64_secret_data), 16 + zlib.MAX_WBITS).decode('utf-8')) + except (ValueError, zlib.error) as error: + ErrorHandler(logger, error, f"Error decoding secret data for {secret_data.metadata['name']}: {error}") + + return secret + + @cache.memoize(timeout=long_cache_time) def k8sHelmChartListGet(username_role, user_token, namespace): k8sClientConfigGet(username_role, user_token) + latest_releases = {} + HAS_CHART = False CHART_LIST = {} CHART_DATA = list() try: secret_list = k8s_client.CoreV1Api().list_namespaced_secret(namespace, _request_timeout=1, timeout_seconds=1) + except ApiException as error: + if error.status != 404: + ErrorHandler(logger, error, "get helm release - %s" % error.status) + + if secret_list: + # 1 Find The Latest Helm Release for secret in secret_list.items: if secret.type == 'helm.sh/release.v1': - base64_secret_data = str(base64_decode(secret.data['release']), 'UTF-8') - secret_data = json.loads(zlib.decompress(base64_decode(base64_secret_data), 16 + zlib.MAX_WBITS).decode('utf-8')) + parts = secret.metadata.name.split('.') + if len(parts) >= 6: # sh.helm.release.v1.chart.vX + chart_name = parts[4] + version = int(parts[5][1:]) # Remove the 'v' prefix and convert to int + + # Check if this is a newer version than what we have + if chart_name not in latest_releases or version > latest_releases[chart_name][1]: + latest_releases[chart_name] = (secret, version) + + # 2 Get the latest Helm Release Data + for chart_name, (secret, version) in latest_releases.items(): + if secret.data and 'release' in secret.data: + secret_data = decode_secret_date(secret) + + if secret_data: if 'icon' in secret_data['chart']['metadata']: helm_icon = secret_data['chart']['metadata']['icon'] else: @@ -56,14 +89,15 @@ def k8sHelmChartListGet(username_role, user_token, namespace): if secret_data['chart']["lock"] and "dependencies" in secret_data['chart']["lock"]: dependencies = secret_data['chart']["lock"]["dependencies"] + # Add the chart data to the list CHART_DATA.append({ 'icon': helm_icon, # X 'status': secret_data['info']['status'], # X 'release_name': release_name, # X + 'release_version': version, # X 'chart_name': chart_name, # X 'chart_version': secret_data['chart']['metadata']['version'], # X 'app_version': helm_api_version, # X - 'revision': secret_data['version'], 'updated': secret_data['info']['last_deployed'], # X # Resources "deployments": [deployment.metadata.name for deployment in deployment_list], @@ -80,32 +114,102 @@ def k8sHelmChartListGet(username_role, user_token, namespace): #"dependencies": dependencies }) HAS_CHART = True - for chart in CHART_DATA: - if chart['release_name'] not in CHART_LIST.keys(): - CHART_LIST[chart['release_name']] = list() - CHART_LIST[chart['release_name']].append(chart) - return HAS_CHART, CHART_LIST - except ApiException as error: - if error.status != 404: - ErrorHandler(logger, error, "get helm release - %s" % error.status) - return HAS_CHART, CHART_LIST - except Exception as error: - ERROR = "k8sHelmChartListGet: %s" % error - ErrorHandler(logger, "error", ERROR) - return HAS_CHART, CHART_LIST + + # 3 Create a dictionary of charts by release name + for chart in CHART_DATA: + if chart['release_name'] not in CHART_LIST.keys(): + CHART_LIST[chart['release_name']] = list() + CHART_LIST[chart['release_name']].append(chart) + return HAS_CHART, CHART_LIST + + #except ApiException as error: + # if error.status != 404: + # ErrorHandler(logger, error, "get helm release - %s" % error.status) + # return HAS_CHART, CHART_LIST + #except Exception as error: + # ERROR = "k8sHelmChartListGet: %s" % error + # ErrorHandler(logger, "error", ERROR) + # return HAS_CHART, CHART_LIST - ############################################################## +############################################################## ## Get Chart Release ############################################################## @cache.memoize(timeout=long_cache_time) -def k8sHelmChartReleaseGet(chart_list, selected=None): - chart_name = None - chart_data = None +def k8sHelmChartReleaseGet(username_role, user_token, namespace, release_name, release_version): + k8sClientConfigGet(username_role, user_token) + CHART_DATA = None + secret_data = None - for name, release in chart_list.items(): - if name == selected: - chart_name = name - chart_data = release + # sh.helm.release.v1.chart.vX + secret_name = f"sh.helm.release.v1.{release_name}.v{release_version}" + + try: + secret = k8s_client.CoreV1Api().read_namespaced_secret( + namespace=namespace, + name=secret_name + ) + except Exception as error: + if error.status != 404: + ErrorHandler(logger, error, "k8sHelmChartReleaseGet: get helm release - %s" % error.status) + else: + ERROR = "k8sHelmChartReleaseGet: %s" % error + ErrorHandler(logger, "error", ERROR) + + if secret: + secret_data = decode_secret_date(secret) + + if secret_data: + if 'icon' in secret_data['chart']['metadata']: + helm_icon = secret_data['chart']['metadata']['icon'] + else: + helm_icon = None + if 'appVersion' in secret_data['chart']['metadata']: + helm_api_version = secret_data['chart']['metadata']['appVersion'] + else: + helm_api_version = None - return chart_name, chart_data \ No newline at end of file + ## Get the Kubernetes resources for the release + chart_name = secret_data['chart']['metadata']['name'] + release_name = secret_data['name'] + label_selector = f"app.kubernetes.io/instance={release_name}" + deployment_list = k8s_client.AppsV1Api().list_namespaced_deployment(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + daemonset_list = k8s_client.AppsV1Api().list_namespaced_daemon_set(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + stateful_set_list = k8s_client.AppsV1Api().list_namespaced_stateful_set(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + svc_list = k8s_client.CoreV1Api().list_namespaced_service(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + ingress_list = k8s_client.NetworkingV1Api().list_namespaced_ingress(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + sa_list = k8s_client.CoreV1Api().list_namespaced_service_account(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + secret_list = k8s_client.CoreV1Api().list_namespaced_secret(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + configma_list = k8s_client.CoreV1Api().list_namespaced_config_map(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + pvc_list = k8s_client.CoreV1Api().list_namespaced_persistent_volume_claim(namespace, label_selector=label_selector, _request_timeout=1, timeout_seconds=1).items + dependencies = None + if "lock" in secret_data['chart']: + if secret_data['chart']["lock"] and "dependencies" in secret_data['chart']["lock"]: + dependencies = secret_data['chart']["lock"]["dependencies"] + + # Add the chart data to the list + CHART_DATA = { + 'icon': helm_icon, # X + 'status': secret_data['info']['status'], # X + 'release_name': release_name, # X + 'release_version': release_version, # X + 'chart_name': chart_name, # X + 'chart_version': secret_data['chart']['metadata']['version'], # X + 'app_version': helm_api_version, # X + 'updated': secret_data['info']['last_deployed'], # X + # Resources + "deployments": [deployment.metadata.name for deployment in deployment_list], + "daemonset": [daemonset.metadata.name for daemonset in daemonset_list], + "statefulsets": [ss.metadata.name for ss in stateful_set_list], + "services": [svc.metadata.name for svc in svc_list], + "ingresses": [ingress.metadata.name for ingress in ingress_list], + "secrets": [secret.metadata.name for secret in secret_list], + "configmaps": [configmap.metadata.name for configmap in configma_list], + "service_accounts": [sa.metadata.name for sa in sa_list], + "persistent_volume_claims": [pvc.metadata.name for pvc in pvc_list], + "values": json2yaml(secret_data['chart']["values"]), + "manifests": secret_data["manifest"], + #"dependencies": dependencies + } + + return CHART_DATA diff --git a/src/kubedash/plugins/helm/templates/helm-chart-data.html.j2 b/src/kubedash/plugins/helm/templates/helm-chart-data.html.j2 index f494d6b0..7467037b 100644 --- a/src/kubedash/plugins/helm/templates/helm-chart-data.html.j2 +++ b/src/kubedash/plugins/helm/templates/helm-chart-data.html.j2 @@ -23,10 +23,7 @@
Chart Data
- - {% for rd in chart_data %} - {% if loop.last %} - +
@@ -110,7 +107,7 @@

Values

-
{{ rd["values"] }}
+
{{ chart_data["values"] }}
@@ -124,7 +121,7 @@

Manifests

-
{{ rd.manifests }}
+
{{ chart_data.manifests }}
@@ -146,7 +143,7 @@ - {% for deployment in rd.deployments %} + {% for deployment in chart_data.deployments %} Deployment @@ -159,7 +156,7 @@ {% endfor %} - {% for daemonset in rd.daemonset %} + {% for daemonset in chart_data.daemonset %} Daemonset @@ -172,7 +169,7 @@ {% endfor %} - {% for ss in rd.statefulsets %} + {% for ss in chart_data.statefulsets %} Stateful Set @@ -185,7 +182,7 @@ {% endfor %} - {% for service in rd.services %} + {% for service in chart_data.services %} Service @@ -198,7 +195,7 @@ {% endfor %} - {% for ingress in rd.ingresses %} + {% for ingress in chart_data.ingresses %} Ingress @@ -211,7 +208,7 @@ {% endfor %} - {% for sa in rd.service_accounts %} + {% for sa in chart_data.service_accounts %} Aervice Account @@ -224,7 +221,7 @@ {% endfor %} - {% for secret in rd.secrets %} + {% for secret in chart_data.secrets %} Secret @@ -237,7 +234,7 @@ {% endfor %} - {% for configmap in rd.configmaps %} + {% for configmap in chart_data.configmaps %} Configmap @@ -250,7 +247,7 @@ {% endfor %} - {% for pvc in rd.persistent_volume_claims %} + {% for pvc in chart_data.persistent_volume_claims %} Persistent Volume Claim @@ -272,7 +269,7 @@ {# - {% if rd.dependencies %} + {% if chart_data.dependencies %} {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} -{% include "segments/highlight_snipet.html.j2"%} +{% include "segments/datatable_snippet.html.j2" %} +{% include "segments/highlight_snippet.html.j2"%} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/plugins/helm/templates/helm-charts.html.j2 b/src/kubedash/plugins/helm/templates/helm-charts.html.j2 index ba4ca1bb..4d1216be 100644 --- a/src/kubedash/plugins/helm/templates/helm-charts.html.j2 +++ b/src/kubedash/plugins/helm/templates/helm-charts.html.j2 @@ -39,7 +39,6 @@ {% for name, release in chart_list.items() %} {% for rd in release %} - {% if loop.last %} {% if selected == name %} {% else %} @@ -54,7 +53,8 @@
- + + {{ name }}
@@ -67,10 +67,9 @@ {{ rd.chart_name }}-{{ rd.chart_version }} {{ rd.app_version }} - {{ rd.revision }} + {{ rd.release_version }} {{ rd.updated }} - {% endif %} {% endfor %} {% endfor %} @@ -85,5 +84,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/plugins/registry/templates/registry-image-list.html.j2 b/src/kubedash/plugins/registry/templates/registry-image-list.html.j2 index b846d35f..31180f50 100644 --- a/src/kubedash/plugins/registry/templates/registry-image-list.html.j2 +++ b/src/kubedash/plugins/registry/templates/registry-image-list.html.j2 @@ -55,5 +55,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/plugins/registry/templates/registry-image-tag-data.html.j2 b/src/kubedash/plugins/registry/templates/registry-image-tag-data.html.j2 index 2b8297d8..a282df84 100644 --- a/src/kubedash/plugins/registry/templates/registry-image-tag-data.html.j2 +++ b/src/kubedash/plugins/registry/templates/registry-image-tag-data.html.j2 @@ -423,5 +423,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/plugins/registry/templates/registry-image-tag-list.html.j2 b/src/kubedash/plugins/registry/templates/registry-image-tag-list.html.j2 index 0200a9d7..2b1e7c7c 100644 --- a/src/kubedash/plugins/registry/templates/registry-image-tag-list.html.j2 +++ b/src/kubedash/plugins/registry/templates/registry-image-tag-list.html.j2 @@ -79,5 +79,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/plugins/registry/templates/registry.html.j2 b/src/kubedash/plugins/registry/templates/registry.html.j2 index 80b2e22b..c6068416 100644 --- a/src/kubedash/plugins/registry/templates/registry.html.j2 +++ b/src/kubedash/plugins/registry/templates/registry.html.j2 @@ -207,5 +207,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/cluster-role-binding.html.j2 b/src/kubedash/templates/cluster-permission/cluster-role-binding.html.j2 index 1c2ed360..c764fc35 100644 --- a/src/kubedash/templates/cluster-permission/cluster-role-binding.html.j2 +++ b/src/kubedash/templates/cluster-permission/cluster-role-binding.html.j2 @@ -99,5 +99,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/cluster-role-data.html.j2 b/src/kubedash/templates/cluster-permission/cluster-role-data.html.j2 index eb19c464..71e83245 100644 --- a/src/kubedash/templates/cluster-permission/cluster-role-data.html.j2 +++ b/src/kubedash/templates/cluster-permission/cluster-role-data.html.j2 @@ -7,7 +7,7 @@ @@ -34,50 +34,64 @@ - {% for cr in cluster_roles %} - {% if cr_name == cr.name %} - {% for rules in cr.rules %} + {% if cluster_role %} + {% if cluster_role.rules %} + {% for rules in cluster_role.rules %} + + + {% if rules.api_groups %} + {% for ag in rules.api_groups %} + {{ ag }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.api_groups }} + {% endif %} + + + {% if rules.resource_names %} + {% for rn in rules.resource_names %} + {{ rn }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.resource_names }} + {% endif %} + + + {% if rules.resources %} + {% for r in rules.resources %} + {{ r }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.resources }} + {% endif %} + + + {% if rules.verbs %} + {% for v in rules.verbs %} + {{ v }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.verbs }} + {% endif %} + + + {% endfor %} + {% else %} - - {% if rules.api_groups %} - {% for ag in rules.api_groups %} - {{ ag }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.api_groups }} - {% endif %} - - - {% if rules.resource_names %} - {% for rn in rules.resource_names %} - {{ rn }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.resource_names }} - {% endif %} - - - {% if rules.resources %} - {% for r in rules.resources %} - {{ r }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.resources }} - {% endif %} - - - {% if rules.verbs %} - {% for v in rules.verbs %} - {{ v }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.verbs }} - {% endif %} - + + No rules found. + + - {% endfor %} + {% endif %} + {% else %} + + + No role. + + + {% endif %} - {% endfor %} @@ -86,5 +100,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/cluster-role.html.j2 b/src/kubedash/templates/cluster-permission/cluster-role.html.j2 index eaf13a70..913a029c 100644 --- a/src/kubedash/templates/cluster-permission/cluster-role.html.j2 +++ b/src/kubedash/templates/cluster-permission/cluster-role.html.j2 @@ -73,5 +73,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/role-binding.html.j2 b/src/kubedash/templates/cluster-permission/role-binding.html.j2 index feaf07a5..79f5fc5b 100644 --- a/src/kubedash/templates/cluster-permission/role-binding.html.j2 +++ b/src/kubedash/templates/cluster-permission/role-binding.html.j2 @@ -98,5 +98,5 @@ {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/role-data.html.j2 b/src/kubedash/templates/cluster-permission/role-data.html.j2 index 9a00ee07..96ccf3a7 100644 --- a/src/kubedash/templates/cluster-permission/role-data.html.j2 +++ b/src/kubedash/templates/cluster-permission/role-data.html.j2 @@ -34,50 +34,64 @@ - {% for r in roles %} - {% if r_name == r.name %} - {% for rules in r.rules %} + {% if role %} + {% if role.rules %} + {% for rules in role.rules %} + + + {% if rules.api_groups %} + {% for ag in rules.api_groups %} + {{ ag }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.api_groups }} + {% endif %} + + + {% if rules.resource_names %} + {% for rn in rules.resource_names %} + {{ rn }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.resource_names }} + {% endif %} + + + {% if rules.resources %} + {% for r in rules.resources %} + {{ r }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.resources }} + {% endif %} + + + {% if rules.verbs %} + {% for v in rules.verbs %} + {{ v }}{% if not loop.last %}
{% endif %} + {% endfor %} + {% else %} + {{ rules.verbs }} + {% endif %} + + + {% endfor %} + {% else %} - - {% if rules.api_groups %} - {% for ag in rules.api_groups %} - {{ ag }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.api_groups }} - {% endif %} - - - {% if rules.resource_names %} - {% for rn in rules.resource_names %} - {{ rn }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.resource_names }} - {% endif %} - - - {% if rules.resources %} - {% for r in rules.resources %} - {{ r }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.resources }} - {% endif %} - - - {% if rules.verbs %} - {% for v in rules.verbs %} - {{ v }}{% if not loop.last %}
{% endif %} - {% endfor %} - {% else %} - {{ rules.verbs }} - {% endif %} - + + No rules found. + + + + {% endif %} + {% else %} + + + No role. + + - {% endfor %} {% endif %} - {% endfor %} @@ -86,5 +100,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/role.html.j2 b/src/kubedash/templates/cluster-permission/role.html.j2 index 954e7646..3bc00b83 100644 --- a/src/kubedash/templates/cluster-permission/role.html.j2 +++ b/src/kubedash/templates/cluster-permission/role.html.j2 @@ -74,5 +74,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster-permission/service-account.html.j2 b/src/kubedash/templates/cluster-permission/service-account.html.j2 index 6ca61920..7488c95c 100644 --- a/src/kubedash/templates/cluster-permission/service-account.html.j2 +++ b/src/kubedash/templates/cluster-permission/service-account.html.j2 @@ -72,5 +72,5 @@ {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} diff --git a/src/kubedash/templates/cluster/crd-data.html.j2 b/src/kubedash/templates/cluster/crd-data.html.j2 index 13f1e614..79404dd7 100644 --- a/src/kubedash/templates/cluster/crd-data.html.j2 +++ b/src/kubedash/templates/cluster/crd-data.html.j2 @@ -56,5 +56,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/templates/cluster/crd.html.j2 b/src/kubedash/templates/cluster/crd.html.j2 index b89f5943..86821360 100644 --- a/src/kubedash/templates/cluster/crd.html.j2 +++ b/src/kubedash/templates/cluster/crd.html.j2 @@ -63,5 +63,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/templates/cluster/namespace-data.html.j2 b/src/kubedash/templates/cluster/namespace-data.html.j2 index 91719f62..63ae4e66 100644 --- a/src/kubedash/templates/cluster/namespace-data.html.j2 +++ b/src/kubedash/templates/cluster/namespace-data.html.j2 @@ -43,6 +43,7 @@ Created: {{ ns_data.created }} + Annotations: @@ -116,5 +118,5 @@ {% endblock %} {% block add_head_css %} -{% include "segments/datatable_snipet.html.j2" %} +{% include "segments/datatable_snippet.html.j2" %} {% endblock %} \ No newline at end of file diff --git a/src/kubedash/templates/cluster/namespace.html.j2 b/src/kubedash/templates/cluster/namespace.html.j2 index e31413b7..dd193aa4 100644 --- a/src/kubedash/templates/cluster/namespace.html.j2 +++ b/src/kubedash/templates/cluster/namespace.html.j2 @@ -13,12 +13,14 @@