From 94676df329e09dcc8a2c14fb2e98ddfd4a075639 Mon Sep 17 00:00:00 2001 From: Maxime Bajeux Date: Mon, 20 Jul 2020 00:49:49 +0200 Subject: [PATCH] feat(k8s/cluster): Show the cluster leader (#4027) * feat(cluster): Show the cluster leader * feat(cluster): Restrict leader label only to admin users * feat(kubernetes): minor UI update * feat(endpoint): move all KubernetesEndpoint related code to a single endpoint sub-folder and change few things * fix(k8s/cluster): fix conflict leftover * feat(k8s/cluster): review component leader UX * refactor(k8s/node): remove useless call to endpoints * refactor(k8s/endpoint): relocate variable declaration Co-authored-by: Anthony Lapenna --- .../nodes-datatable/nodesDatatable.html | 8 +--- app/kubernetes/endpoint/converter.js | 20 +++++++++ app/kubernetes/endpoint/models.js | 17 ++++++++ app/kubernetes/endpoint/rest.js | 25 +++++++++++ app/kubernetes/endpoint/service.js | 33 ++++++++++++++ app/kubernetes/views/cluster/cluster.html | 43 ++++++++++++++++--- .../views/cluster/clusterController.js | 32 ++++++++++++-- 7 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 app/kubernetes/endpoint/converter.js create mode 100644 app/kubernetes/endpoint/models.js create mode 100644 app/kubernetes/endpoint/rest.js create mode 100644 app/kubernetes/endpoint/service.js diff --git a/app/kubernetes/components/datatables/nodes-datatable/nodesDatatable.html b/app/kubernetes/components/datatables/nodes-datatable/nodesDatatable.html index 7d90d2379..c6526a30e 100644 --- a/app/kubernetes/components/datatables/nodes-datatable/nodesDatatable.html +++ b/app/kubernetes/components/datatables/nodes-datatable/nodesDatatable.html @@ -114,13 +114,9 @@ dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" > - - {{ item.Name }} - - - - {{ item.Name }} + {{ item.Name }} + {{ item.Name }} {{ item.Role }} {{ item.Status }} KubernetesEndpointConverter.apiToEndpoint(item)); + } catch (err) { + throw new PortainerError('Unable to retrieve endpoints', err); + } + } + + get(namespace) { + return this.$async(this.getAllAsync, namespace); + } +} + +export default KubernetesEndpointService; +angular.module('portainer.kubernetes').service('KubernetesEndpointService', KubernetesEndpointService); diff --git a/app/kubernetes/views/cluster/cluster.html b/app/kubernetes/views/cluster/cluster.html index 60bc353ff..ad95331bf 100644 --- a/app/kubernetes/views/cluster/cluster.html +++ b/app/kubernetes/views/cluster/cluster.html @@ -9,6 +9,7 @@
+
+ +
Cluster status
@@ -27,24 +30,50 @@ - - - + + + - - + - -
ComponentStatusErrorComponentStatusError
+
{{ cs.ComponentName }} + healthy unhealthy + {{ cs.ErrorMessage !== '' ? cs.ErrorMessage : '-' }}
+ + + +
+
+ Leader status +
+ + + + + + + + + + + + +
ComponentLeader node
+ {{ ep.Name }} + + {{ ep.HolderIdentity }} +
+
+
diff --git a/app/kubernetes/views/cluster/clusterController.js b/app/kubernetes/views/cluster/clusterController.js index d565c850c..a8ec935c0 100644 --- a/app/kubernetes/views/cluster/clusterController.js +++ b/app/kubernetes/views/cluster/clusterController.js @@ -6,7 +6,17 @@ import { KubernetesResourceReservation } from 'Kubernetes/models/resource-reserv class KubernetesClusterController { /* @ngInject */ - constructor($async, $state, Authentication, Notifications, LocalStorage, KubernetesNodeService, KubernetesApplicationService, KubernetesComponentStatusService) { + constructor( + $async, + $state, + Authentication, + Notifications, + LocalStorage, + KubernetesNodeService, + KubernetesApplicationService, + KubernetesComponentStatusService, + KubernetesEndpointService + ) { this.$async = $async; this.$state = $state; this.Authentication = Authentication; @@ -15,6 +25,7 @@ class KubernetesClusterController { this.KubernetesNodeService = KubernetesNodeService; this.KubernetesApplicationService = KubernetesApplicationService; this.KubernetesComponentStatusService = KubernetesComponentStatusService; + this.KubernetesEndpointService = KubernetesEndpointService; this.onInit = this.onInit.bind(this); this.getNodes = this.getNodes.bind(this); @@ -22,12 +33,13 @@ class KubernetesClusterController { this.getApplicationsAsync = this.getApplicationsAsync.bind(this); this.getComponentStatus = this.getComponentStatus.bind(this); this.getComponentStatusAsync = this.getComponentStatusAsync.bind(this); + this.getEndpointsAsync = this.getEndpointsAsync.bind(this); } async getComponentStatusAsync() { try { - this.ComponentStatuses = await this.KubernetesComponentStatusService.get(); - this.hasUnhealthyComponentStatus = _.find(this.ComponentStatuses, { Healthy: false }) ? true : false; + this.componentStatuses = await this.KubernetesComponentStatusService.get(); + this.hasUnhealthyComponentStatus = _.find(this.componentStatuses, { Healthy: false }) ? true : false; } catch (err) { this.Notifications.error('Failure', err, 'Unable to retrieve cluster component statuses'); } @@ -37,6 +49,19 @@ class KubernetesClusterController { return this.$async(this.getComponentStatusAsync); } + async getEndpointsAsync() { + try { + const endpoints = await this.KubernetesEndpointService.get('kube-system'); + this.endpoints = _.filter(endpoints, (ep) => ep.HolderIdentity); + } catch (err) { + this.Notifications.error('Failure', err, 'Unable to retrieve endpoints'); + } + } + + getEndpoints() { + return this.$async(this.getEndpointsAsync); + } + async getNodesAsync() { try { const nodes = await this.KubernetesNodeService.get(); @@ -92,6 +117,7 @@ class KubernetesClusterController { await this.getNodes(); if (this.isAdmin) { + await this.getEndpoints(); await this.getComponentStatus(); await this.getApplications(); }