diff --git a/.changeset/clean-lobsters-brake.md b/.changeset/clean-lobsters-brake.md new file mode 100644 index 0000000000..f6da6e986e --- /dev/null +++ b/.changeset/clean-lobsters-brake.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-kubernetes-backend': minor +--- + +Allow fetching pod metrics limited by a `labelSelector`. + +This is used by the Kubernetes tab on a components' page and leads to much smaller responses being received from Kubernetes, especially with larger Kubernetes clusters. diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts index e24c08cafd..4397bce441 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts @@ -918,7 +918,7 @@ describe('getKubernetesObjectsByEntity', () => { { errorType: 'FETCH_ERROR', message: - 'request to https://fails/api/v1/pods?labelSelector=backstage.io/kubernetes-id=test-component failed, reason: socket error', + 'request to https://fails/api/v1/pods?labelSelector=backstage.io%2Fkubernetes-id%3Dtest-component failed, reason: socket error', }, ], }, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 8441effabd..79003ae1ca 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -283,7 +283,9 @@ export class KubernetesFanOutHandler { })), namespace, }) - .then(result => this.getMetricsForPods(clusterDetailsItem, result)) + .then(result => + this.getMetricsForPods(clusterDetailsItem, labelSelector, result), + ) .catch( (e): Promise => e.name === 'FetchError' @@ -365,6 +367,7 @@ export class KubernetesFanOutHandler { async getMetricsForPods( clusterDetails: ClusterDetails, + labelSelector: string, result: FetchResponseWrapper, ): Promise { if (clusterDetails.skipMetricsLookup) { @@ -385,6 +388,7 @@ export class KubernetesFanOutHandler { const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces( clusterDetails, namespaces, + labelSelector, ); result.errors.push(...podMetrics.errors); diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index 48bea3106b..b2be199d50 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -119,6 +119,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { fetchPodMetricsByNamespaces( clusterDetails: ClusterDetails, namespaces: Set, + labelSelector?: string, ): Promise { const fetchResults = Array.from(namespaces).map(async ns => { const [podMetrics, podList] = await Promise.all([ @@ -128,8 +129,9 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { 'v1beta1', 'pods', ns, + labelSelector, ), - this.fetchResource(clusterDetails, '', 'v1', 'pods', ns), + this.fetchResource(clusterDetails, '', 'v1', 'pods', ns, labelSelector), ]); if (podMetrics.ok && podList.ok) { return topPods( @@ -213,7 +215,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { } if (labelSelector) { - url.search = `labelSelector=${labelSelector}`; + url.search = `labelSelector=${encode(labelSelector)}`; } return fetch(url, requestInit); diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index e460edbc29..15ed1662de 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -56,6 +56,7 @@ export interface KubernetesFetcher { fetchPodMetricsByNamespaces( clusterDetails: ClusterDetails, namespaces: Set, + labelSelector?: string, ): Promise; }