mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
fix(gke): port metrics to the backend EE-5447 (#9041)
This commit is contained in:
parent
e996d29d52
commit
704d70c99b
15 changed files with 441 additions and 247 deletions
|
@ -1,114 +0,0 @@
|
|||
import angular from 'angular';
|
||||
import PortainerError from 'Portainer/error';
|
||||
import { KubernetesCommonParams } from 'Kubernetes/models/common/params';
|
||||
|
||||
class KubernetesMetricsService {
|
||||
/* @ngInject */
|
||||
constructor($async, KubernetesMetrics) {
|
||||
this.$async = $async;
|
||||
this.KubernetesMetrics = KubernetesMetrics;
|
||||
|
||||
this.capabilitiesAsync = this.capabilitiesAsync.bind(this);
|
||||
|
||||
this.getPodAsync = this.getPodAsync.bind(this);
|
||||
this.getNodeAsync = this.getNodeAsync.bind(this);
|
||||
|
||||
this.getPodsAsync = this.getPodsAsync.bind(this);
|
||||
this.getNodesAsync = this.getNodesAsync.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET
|
||||
*/
|
||||
async capabilitiesAsync(endpointID) {
|
||||
try {
|
||||
await this.KubernetesMetrics().capabilities({ endpointId: endpointID }).$promise;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to retrieve metrics', err);
|
||||
}
|
||||
}
|
||||
|
||||
capabilities(endpointID) {
|
||||
return this.$async(this.capabilitiesAsync, endpointID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stats of Node
|
||||
*
|
||||
* @param {string} nodeName
|
||||
*/
|
||||
async getNodeAsync(nodeName) {
|
||||
try {
|
||||
const params = new KubernetesCommonParams();
|
||||
params.id = nodeName;
|
||||
const data = await this.KubernetesMetrics().getNode(params).$promise;
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to retrieve node stats', err);
|
||||
}
|
||||
}
|
||||
|
||||
getNode(nodeName) {
|
||||
return this.$async(this.getNodeAsync, nodeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stats
|
||||
*
|
||||
* @param {string} namespace
|
||||
* @param {string} podName
|
||||
*/
|
||||
async getPodAsync(namespace, podName) {
|
||||
try {
|
||||
const params = new KubernetesCommonParams();
|
||||
params.id = podName;
|
||||
const data = await this.KubernetesMetrics(namespace).getPod(params).$promise;
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to retrieve pod stats', err);
|
||||
}
|
||||
}
|
||||
|
||||
getPod(namespace, podName) {
|
||||
return this.$async(this.getPodAsync, namespace, podName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stats of Nodes in cluster
|
||||
*
|
||||
* @param {string} endpointID
|
||||
*/
|
||||
async getNodesAsync(endpointID) {
|
||||
try {
|
||||
const data = await this.KubernetesMetrics().getNodes({ endpointId: endpointID }).$promise;
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to retrieve nodes stats', err);
|
||||
}
|
||||
}
|
||||
|
||||
getNodes(endpointID) {
|
||||
return this.$async(this.getNodesAsync, endpointID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stats of Pods in a namespace
|
||||
*
|
||||
* @param {string} namespace
|
||||
*/
|
||||
async getPodsAsync(namespace) {
|
||||
try {
|
||||
const data = await this.KubernetesMetrics(namespace).getPods().$promise;
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to retrieve pod stats', err);
|
||||
}
|
||||
}
|
||||
|
||||
getPods(namespace) {
|
||||
return this.$async(this.getPodsAsync, namespace);
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesMetricsService;
|
||||
angular.module('portainer.kubernetes').service('KubernetesMetricsService', KubernetesMetricsService);
|
|
@ -1,39 +0,0 @@
|
|||
angular.module('portainer.kubernetes').factory('KubernetesMetrics', [
|
||||
'$resource',
|
||||
'API_ENDPOINT_ENDPOINTS',
|
||||
'EndpointProvider',
|
||||
function KubernetesMetrics($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider) {
|
||||
'use strict';
|
||||
return function (namespace) {
|
||||
const url = API_ENDPOINT_ENDPOINTS + '/:endpointId/kubernetes/apis/metrics.k8s.io/v1beta1';
|
||||
const podUrl = `${url}${namespace ? '/namespaces/:namespace' : ''}/pods/:id`;
|
||||
|
||||
return $resource(
|
||||
url,
|
||||
{
|
||||
endpointId: EndpointProvider.endpointID,
|
||||
namespace: namespace,
|
||||
},
|
||||
{
|
||||
capabilities: { method: 'GET' },
|
||||
getPod: {
|
||||
method: 'GET',
|
||||
url: podUrl,
|
||||
},
|
||||
getNode: {
|
||||
method: 'GET',
|
||||
url: `${url}/nodes/:id`,
|
||||
},
|
||||
getPods: {
|
||||
method: 'GET',
|
||||
url: `${url}/namespaces/:namespace/pods`,
|
||||
},
|
||||
getNodes: {
|
||||
method: 'GET',
|
||||
url: `${url}/nodes`,
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
]);
|
|
@ -4,10 +4,11 @@ import _ from 'lodash-es';
|
|||
import filesizeParser from 'filesize-parser';
|
||||
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
|
||||
import KubernetesPodConverter from 'Kubernetes/pod/converter';
|
||||
import { getMetricsForPod } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesApplicationStatsController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $interval, $document, Notifications, KubernetesPodService, KubernetesNodeService, KubernetesMetricsService, ChartService) {
|
||||
constructor($async, $state, $interval, $document, Notifications, KubernetesPodService, KubernetesNodeService, ChartService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$interval = $interval;
|
||||
|
@ -15,7 +16,6 @@ class KubernetesApplicationStatsController {
|
|||
this.Notifications = Notifications;
|
||||
this.KubernetesPodService = KubernetesPodService;
|
||||
this.KubernetesNodeService = KubernetesNodeService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
this.ChartService = ChartService;
|
||||
|
||||
this.onInit = this.onInit.bind(this);
|
||||
|
@ -84,7 +84,7 @@ class KubernetesApplicationStatsController {
|
|||
getStats() {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const stats = await this.KubernetesMetricsService.getPod(this.state.transition.namespace, this.state.transition.podName);
|
||||
const stats = await getMetricsForPod(this.$state.params.endpointId, this.state.transition.namespace, this.state.transition.podName);
|
||||
const container = _.find(stats.containers, { name: this.state.transition.containerName });
|
||||
if (container) {
|
||||
const memory = filesizeParser(container.usage.memory);
|
||||
|
@ -126,7 +126,7 @@ class KubernetesApplicationStatsController {
|
|||
};
|
||||
|
||||
try {
|
||||
await this.KubernetesMetricsService.getPod(this.state.transition.namespace, this.state.transition.podName);
|
||||
await getMetricsForPod(this.$state.params.endpointId, this.state.transition.namespace, this.state.transition.podName);
|
||||
} catch (error) {
|
||||
this.state.getMetrics = false;
|
||||
this.state.viewReady = true;
|
||||
|
|
|
@ -3,27 +3,17 @@ import _ from 'lodash-es';
|
|||
import filesizeParser from 'filesize-parser';
|
||||
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
|
||||
import { KubernetesResourceReservation } from 'Kubernetes/models/resource-reservation/models';
|
||||
import { getMetricsForAllNodes } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesClusterController {
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$async,
|
||||
$state,
|
||||
Authentication,
|
||||
Notifications,
|
||||
LocalStorage,
|
||||
KubernetesNodeService,
|
||||
KubernetesMetricsService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesEndpointService
|
||||
) {
|
||||
constructor($async, $state, Notifications, LocalStorage, Authentication, KubernetesNodeService, KubernetesApplicationService, KubernetesEndpointService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.Authentication = Authentication;
|
||||
this.Notifications = Notifications;
|
||||
this.LocalStorage = LocalStorage;
|
||||
this.KubernetesNodeService = KubernetesNodeService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
this.KubernetesEndpointService = KubernetesEndpointService;
|
||||
|
||||
|
@ -108,7 +98,7 @@ class KubernetesClusterController {
|
|||
|
||||
async getResourceUsage(endpointId) {
|
||||
try {
|
||||
const nodeMetrics = await this.KubernetesMetricsService.getNodes(endpointId);
|
||||
const nodeMetrics = await getMetricsForAllNodes(endpointId);
|
||||
const resourceUsageList = nodeMetrics.items.map((i) => i.usage);
|
||||
const clusterResourceUsage = resourceUsageList.reduce((total, u) => {
|
||||
total.CPU += KubernetesResourceReservationHelper.parseCPU(u.cpu);
|
||||
|
|
|
@ -9,6 +9,7 @@ import { KubernetesNodeTaintEffects, KubernetesNodeAvailabilities } from 'Kubern
|
|||
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
||||
import { KubernetesNodeHelper } from 'Kubernetes/node/helper';
|
||||
import { confirmUpdateNode } from '@/react/kubernetes/cluster/NodeView/ConfirmUpdateNode';
|
||||
import { getMetricsForNode } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesNodeController {
|
||||
/* @ngInject */
|
||||
|
@ -22,7 +23,6 @@ class KubernetesNodeController {
|
|||
KubernetesPodService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesEndpointService,
|
||||
KubernetesMetricsService,
|
||||
Authentication
|
||||
) {
|
||||
this.$async = $async;
|
||||
|
@ -34,7 +34,6 @@ class KubernetesNodeController {
|
|||
this.KubernetesPodService = KubernetesPodService;
|
||||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
this.KubernetesEndpointService = KubernetesEndpointService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
this.Authentication = Authentication;
|
||||
|
||||
this.onInit = this.onInit.bind(this);
|
||||
|
@ -300,7 +299,7 @@ class KubernetesNodeController {
|
|||
async getNodeUsageAsync() {
|
||||
try {
|
||||
const nodeName = this.$transition$.params().name;
|
||||
const node = await this.KubernetesMetricsService.getNode(nodeName);
|
||||
const node = await getMetricsForNode(this.$state.params.endpointId, nodeName);
|
||||
this.resourceUsage = new KubernetesResourceReservation();
|
||||
this.resourceUsage.CPU = KubernetesResourceReservationHelper.parseCPU(node.usage.cpu);
|
||||
this.resourceUsage.Memory = KubernetesResourceReservationHelper.megaBytesValue(node.usage.memory);
|
||||
|
|
|
@ -3,17 +3,17 @@ import moment from 'moment';
|
|||
import filesizeParser from 'filesize-parser';
|
||||
import KubernetesResourceReservationHelper from 'Kubernetes/helpers/resourceReservationHelper';
|
||||
import { PORTAINER_FADEOUT } from '@/constants';
|
||||
import { getMetricsForNode } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesNodeStatsController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $interval, $document, Notifications, KubernetesNodeService, KubernetesMetricsService, ChartService) {
|
||||
constructor($async, $state, $interval, $document, Notifications, KubernetesNodeService, ChartService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$interval = $interval;
|
||||
this.$document = $document;
|
||||
this.Notifications = Notifications;
|
||||
this.KubernetesNodeService = KubernetesNodeService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
this.ChartService = ChartService;
|
||||
|
||||
this.onInit = this.onInit.bind(this);
|
||||
|
@ -79,7 +79,7 @@ class KubernetesNodeStatsController {
|
|||
getStats() {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const stats = await this.KubernetesMetricsService.getNode(this.state.transition.nodeName);
|
||||
const stats = await getMetricsForNode(this.$state.params.endpointId, this.state.transition.nodeName);
|
||||
if (stats) {
|
||||
const memory = filesizeParser(stats.usage.memory);
|
||||
const cpu = KubernetesResourceReservationHelper.parseCPU(stats.usage.cpu);
|
||||
|
@ -111,7 +111,7 @@ class KubernetesNodeStatsController {
|
|||
};
|
||||
|
||||
try {
|
||||
const nodeMetrics = await this.KubernetesMetricsService.getNode(this.state.transition.nodeName);
|
||||
const nodeMetrics = await getMetricsForNode(this.$state.params.endpointId, this.state.transition.nodeName);
|
||||
|
||||
if (nodeMetrics) {
|
||||
const node = await this.KubernetesNodeService.get(this.state.transition.nodeName);
|
||||
|
|
|
@ -11,23 +11,13 @@ import { buildConfirmButton } from '@@/modals/utils';
|
|||
import { confirm } from '@@/modals/confirm';
|
||||
import { getIsRBACEnabled } from '@/react/kubernetes/cluster/getIsRBACEnabled';
|
||||
import { ModalType } from '@@/modals/Modal/types';
|
||||
import { getMetricsForAllNodes } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesConfigureController {
|
||||
/* #region CONSTRUCTOR */
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$async,
|
||||
$state,
|
||||
$scope,
|
||||
Notifications,
|
||||
KubernetesStorageService,
|
||||
EndpointService,
|
||||
EndpointProvider,
|
||||
KubernetesResourcePoolService,
|
||||
KubernetesIngressService,
|
||||
KubernetesMetricsService
|
||||
) {
|
||||
constructor($async, $state, $scope, Notifications, KubernetesStorageService, EndpointService, EndpointProvider, KubernetesResourcePoolService, KubernetesIngressService) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$scope = $scope;
|
||||
|
@ -37,7 +27,6 @@ class KubernetesConfigureController {
|
|||
this.EndpointProvider = EndpointProvider;
|
||||
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
||||
this.KubernetesIngressService = KubernetesIngressService;
|
||||
this.KubernetesMetricsService = KubernetesMetricsService;
|
||||
|
||||
this.IngressClassTypes = KubernetesIngressClassTypes;
|
||||
|
||||
|
@ -192,24 +181,26 @@ class KubernetesConfigureController {
|
|||
}
|
||||
|
||||
enableMetricsServer() {
|
||||
if (this.formValues.UseServerMetrics) {
|
||||
this.state.metrics.userClick = true;
|
||||
this.state.metrics.pending = true;
|
||||
this.KubernetesMetricsService.capabilities(this.endpoint.Id)
|
||||
.then(() => {
|
||||
return this.$async(async () => {
|
||||
if (this.formValues.UseServerMetrics) {
|
||||
this.state.metrics.userClick = true;
|
||||
this.state.metrics.pending = true;
|
||||
try {
|
||||
await getMetricsForAllNodes(this.endpoint.Id);
|
||||
this.state.metrics.isServerRunning = true;
|
||||
this.state.metrics.pending = false;
|
||||
this.state.metrics.userClick = false;
|
||||
this.formValues.UseServerMetrics = true;
|
||||
})
|
||||
.catch(() => {
|
||||
} catch (_) {
|
||||
this.state.metrics.isServerRunning = false;
|
||||
this.state.metrics.pending = false;
|
||||
this.formValues.UseServerMetrics = false;
|
||||
});
|
||||
} else {
|
||||
this.state.metrics.userClick = false;
|
||||
this.formValues.UseServerMetrics = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.state.metrics.userClick = false;
|
||||
this.formValues.UseServerMetrics = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async configureAsync() {
|
||||
|
|
|
@ -16,6 +16,7 @@ import { FeatureId } from '@/react/portainer/feature-flags/enums';
|
|||
import { updateIngressControllerClassMap, getIngressControllerClassMap } from '@/react/kubernetes/cluster/ingressClass/utils';
|
||||
import { confirmUpdate } from '@@/modals/confirm';
|
||||
import { confirmUpdateNamespace } from '@/react/kubernetes/namespaces/ItemView/ConfirmUpdateNamespace';
|
||||
import { getMetricsForAllNodes, getMetricsForAllPods } from '@/react/kubernetes/services/service.ts';
|
||||
|
||||
class KubernetesResourcePoolController {
|
||||
/* #region CONSTRUCTOR */
|
||||
|
@ -28,8 +29,6 @@ class KubernetesResourcePoolController {
|
|||
Notifications,
|
||||
LocalStorage,
|
||||
EndpointService,
|
||||
KubernetesNodeService,
|
||||
KubernetesMetricsService,
|
||||
KubernetesResourceQuotaService,
|
||||
KubernetesResourcePoolService,
|
||||
KubernetesEventService,
|
||||
|
@ -47,8 +46,6 @@ class KubernetesResourcePoolController {
|
|||
Notifications,
|
||||
LocalStorage,
|
||||
EndpointService,
|
||||
KubernetesNodeService,
|
||||
KubernetesMetricsService,
|
||||
KubernetesResourceQuotaService,
|
||||
KubernetesResourcePoolService,
|
||||
KubernetesEventService,
|
||||
|
@ -322,7 +319,7 @@ class KubernetesResourcePoolController {
|
|||
|
||||
async getResourceUsage(namespace) {
|
||||
try {
|
||||
const namespaceMetrics = await this.KubernetesMetricsService.getPods(namespace);
|
||||
const namespaceMetrics = await getMetricsForAllPods(this.$state.params.endpointId, namespace);
|
||||
// extract resource usage of all containers within each pod of the namespace
|
||||
const containerResourceUsageList = namespaceMetrics.items.flatMap((i) => i.containers.map((c) => c.usage));
|
||||
const namespaceResourceUsage = containerResourceUsageList.reduce((total, u) => {
|
||||
|
@ -369,7 +366,7 @@ class KubernetesResourcePoolController {
|
|||
|
||||
const name = this.$state.params.id;
|
||||
|
||||
const [nodes, pools] = await Promise.all([this.KubernetesNodeService.get(), this.KubernetesResourcePoolService.get('', { getQuota: true })]);
|
||||
const [nodes, pools] = await Promise.all([getMetricsForAllNodes, this.KubernetesResourcePoolService.get('', { getQuota: true })]);
|
||||
|
||||
this.ingressControllers = [];
|
||||
if (this.state.ingressAvailabilityPerNamespace) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue