From 6010564860c81dbf7ed742d4d14f43d6e53835cc Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Tue, 21 Nov 2023 10:59:31 -0500 Subject: [PATCH 1/7] Creating extension point for kubernetesClusterSupplier Signed-off-by: Andres Mauricio Gomez P --- .changeset/plenty-falcons-travel.md | 6 ++ plugins/kubernetes-backend/src/plugin.ts | 32 +++++++- plugins/kubernetes-backend/src/types/index.ts | 3 + plugins/kubernetes-backend/src/types/types.ts | 80 +------------------ plugins/kubernetes-node/package.json | 3 +- plugins/kubernetes-node/src/extensions.ts | 20 +++++ plugins/kubernetes-node/src/index.ts | 2 + plugins/kubernetes-node/src/types/types.ts | 79 ++++++++++++++++++ yarn.lock | 1 + 9 files changed, 143 insertions(+), 83 deletions(-) create mode 100644 .changeset/plenty-falcons-travel.md diff --git a/.changeset/plenty-falcons-travel.md b/.changeset/plenty-falcons-travel.md new file mode 100644 index 0000000000..cfc3ffd6f5 --- /dev/null +++ b/.changeset/plenty-falcons-travel.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-kubernetes-node': minor +'@backstage/plugin-kubernetes-backend': patch +--- + +The `kubernetes-node` plugin has been modified to house a new extension points for Kubernetes backend plugin; `KubernetesClusterSupplierExtensionPoint` is introduced . The `kubernetes-backend` plugin was modified to use this new extension point. diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index 83dbae15a0..2d5f1e1d46 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -26,6 +26,9 @@ import { KubernetesObjectsProviderExtensionPoint, kubernetesObjectsProviderExtensionPoint, KubernetesObjectsProvider, + KubernetesClusterSupplierExtensionPoint, + kubernetesClusterSupplierExtensionPoint, + KubernetesClustersSupplier, } from '@backstage/plugin-kubernetes-node'; class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { @@ -45,6 +48,23 @@ class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { } } +class ClusterSuplier implements KubernetesClusterSupplierExtensionPoint { + private clusterSupplier: KubernetesClustersSupplier | undefined; + + getClusterSupplier() { + return this.clusterSupplier; + } + + addClusterSupplier(clusterSupplier: KubernetesClustersSupplier) { + if (this.clusterSupplier) { + throw new Error( + 'Multiple Kubernetes Cluster Suppliers is not supported at this time', + ); + } + this.clusterSupplier = clusterSupplier; + } +} + /** * This is the backend plugin that provides the Kubernetes integration. * @alpha @@ -53,10 +73,15 @@ class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { export const kubernetesPlugin = createBackendPlugin({ pluginId: 'kubernetes', register(env) { - const extensionPoint = new ObjectsProvider(); + const extPointObjectsProvider = new ObjectsProvider(); + const extPointClusterSuplier = new ClusterSuplier(); env.registerExtensionPoint( kubernetesObjectsProviderExtensionPoint, - extensionPoint, + extPointObjectsProvider, + ); + env.registerExtensionPoint( + kubernetesClusterSupplierExtensionPoint, + extPointClusterSuplier, ); env.registerInit({ @@ -76,7 +101,8 @@ export const kubernetesPlugin = createBackendPlugin({ catalogApi, permissions, }) - .setObjectsProvider(extensionPoint.getObjectsProvider()) + .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) + .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) .build(); http.use(router); }, diff --git a/plugins/kubernetes-backend/src/types/index.ts b/plugins/kubernetes-backend/src/types/index.ts index c8413c1aa9..17ce00d020 100644 --- a/plugins/kubernetes-backend/src/types/index.ts +++ b/plugins/kubernetes-backend/src/types/index.ts @@ -17,7 +17,10 @@ export * from './types'; export type { + AuthMetadata, + ClusterDetails, CustomResourcesByEntity, + KubernetesClustersSupplier, KubernetesObjectsByEntity, KubernetesObjectsProvider, } from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 6781dc1161..a4bd38802b 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -16,7 +16,6 @@ import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; -import type { JsonObject } from '@backstage/types'; import type { CustomResourceMatcher, FetchResponse, @@ -25,6 +24,7 @@ import type { } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; import { KubernetesCredential } from '../auth/types'; +import { ClusterDetails } from '@backstage/plugin-kubernetes-node'; /** * @@ -107,20 +107,6 @@ export type KubernetesObjectTypes = // If updating this list, also make sure to update // `objectTypes` and `apiVersionOverrides` in config.d.ts! -/** - * Used to load cluster details from different sources - * @public - */ -export interface KubernetesClustersSupplier { - /** - * Returns the cached list of clusters. - * - * Implementations _should_ cache the clusters and refresh them periodically, - * as getClusters is called whenever the list of clusters is needed. - */ - getClusters(): Promise; -} - /** * @public */ @@ -146,70 +132,6 @@ export interface KubernetesServiceLocator { */ export type ServiceLocatorMethod = 'multiTenant' | 'singleTenant' | 'http'; // TODO implement http -/** - * Provider-specific authentication configuration - * @public - */ -export type AuthMetadata = Record; - -/** - * - * @public - */ -export interface ClusterDetails { - /** - * Specifies the name of the Kubernetes cluster. - */ - name: string; - url: string; - authMetadata: AuthMetadata; - skipTLSVerify?: boolean; - /** - * Whether to skip the lookup to the metrics server to retrieve pod resource usage. - * It is not guaranteed that the Kubernetes distro has the metrics server installed. - */ - skipMetricsLookup?: boolean; - caData?: string | undefined; - caFile?: string | undefined; - /** - * Specifies the link to the Kubernetes dashboard managing this cluster. - * @remarks - * Note that you should specify the app used for the dashboard - * using the dashboardApp property, in order to properly format - * links to kubernetes resources, otherwise it will assume that you're running the standard one. - * @see dashboardApp - * @see dashboardParameters - */ - dashboardUrl?: string; - /** - * Specifies the app that provides the Kubernetes dashboard. - * This will be used for formatting links to kubernetes objects inside the dashboard. - * @remarks - * The existing apps are: standard, rancher, openshift, gke, aks, eks - * Note that it will default to the regular dashboard provided by the Kubernetes project (standard). - * Note that you can add your own formatter by registering it to the clusterLinksFormatters dictionary. - * @defaultValue standard - * @see dashboardUrl - * @example - * ```ts - * import { clusterLinksFormatters } from '@backstage/plugin-kubernetes'; - * clusterLinksFormatters.myDashboard = (options) => ...; - * ``` - */ - dashboardApp?: string; - /** - * Specifies specific parameters used by some dashboard URL formatters. - * This is used by the GKE formatter which requires the project, region and cluster name. - * @see dashboardApp - */ - dashboardParameters?: JsonObject; - /** - * Specifies which custom resources to look for when returning an entity's - * Kubernetes resources. - */ - customResources?: CustomResourceMatcher[]; -} - /** * * @public diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 25e7a5da44..56f4ba01c4 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -30,6 +30,7 @@ "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", - "@backstage/plugin-kubernetes-common": "workspace:^" + "@backstage/plugin-kubernetes-common": "workspace:^", + "@backstage/types": "workspace:^" } } diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts index 152622cf96..3975fa65c3 100644 --- a/plugins/kubernetes-node/src/extensions.ts +++ b/plugins/kubernetes-node/src/extensions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; /** @@ -34,3 +35,22 @@ export const kubernetesObjectsProviderExtensionPoint = createExtensionPoint({ id: 'kubernetes.objects-provider', }); + +/** + * The interface for {@link kubernetesClusterSupplierExtensionPoint}. + * + * @public + */ +export interface KubernetesClusterSupplierExtensionPoint { + addClusterSupplier(clusterSupplier: KubernetesClustersSupplier): void; +} + +/** + * An extension point the exposes the ability to configure a cluster supplier. + * + * @public + */ +export const kubernetesClusterSupplierExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.cluster-supplier', + }); diff --git a/plugins/kubernetes-node/src/index.ts b/plugins/kubernetes-node/src/index.ts index 09ea4123ce..a3da594b43 100644 --- a/plugins/kubernetes-node/src/index.ts +++ b/plugins/kubernetes-node/src/index.ts @@ -32,6 +32,8 @@ export { kubernetesObjectsProviderExtensionPoint, type KubernetesObjectsProviderExtensionPoint, + kubernetesClusterSupplierExtensionPoint, + type KubernetesClusterSupplierExtensionPoint, } from './extensions'; export * from './types'; diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index 182f3ecfeb..f9f60b7085 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -19,6 +19,7 @@ import { KubernetesRequestAuth, ObjectsByEntityResponse, } from '@backstage/plugin-kubernetes-common'; +import { JsonObject } from '@backstage/types'; /** * @@ -51,3 +52,81 @@ export interface KubernetesObjectsByEntity { export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { customResources: CustomResourceMatcher[]; } + +/** + * Provider-specific authentication configuration + * @public + */ +export type AuthMetadata = Record; + +/** + * + * @public + */ +export interface ClusterDetails { + /** + * Specifies the name of the Kubernetes cluster. + */ + name: string; + url: string; + authMetadata: AuthMetadata; + skipTLSVerify?: boolean; + /** + * Whether to skip the lookup to the metrics server to retrieve pod resource usage. + * It is not guaranteed that the Kubernetes distro has the metrics server installed. + */ + skipMetricsLookup?: boolean; + caData?: string | undefined; + caFile?: string | undefined; + /** + * Specifies the link to the Kubernetes dashboard managing this cluster. + * @remarks + * Note that you should specify the app used for the dashboard + * using the dashboardApp property, in order to properly format + * links to kubernetes resources, otherwise it will assume that you're running the standard one. + * @see dashboardApp + * @see dashboardParameters + */ + dashboardUrl?: string; + /** + * Specifies the app that provides the Kubernetes dashboard. + * This will be used for formatting links to kubernetes objects inside the dashboard. + * @remarks + * The existing apps are: standard, rancher, openshift, gke, aks, eks + * Note that it will default to the regular dashboard provided by the Kubernetes project (standard). + * Note that you can add your own formatter by registering it to the clusterLinksFormatters dictionary. + * @defaultValue standard + * @see dashboardUrl + * @example + * ```ts + * import { clusterLinksFormatters } from '@backstage/plugin-kubernetes'; + * clusterLinksFormatters.myDashboard = (options) => ...; + * ``` + */ + dashboardApp?: string; + /** + * Specifies specific parameters used by some dashboard URL formatters. + * This is used by the GKE formatter which requires the project, region and cluster name. + * @see dashboardApp + */ + dashboardParameters?: JsonObject; + /** + * Specifies which custom resources to look for when returning an entity's + * Kubernetes resources. + */ + customResources?: CustomResourceMatcher[]; +} + +/** + * Used to load cluster details from different sources + * @public + */ +export interface KubernetesClustersSupplier { + /** + * Returns the cached list of clusters. + * + * Implementations _should_ cache the clusters and refresh them periodically, + * as getClusters is called whenever the list of clusters is needed. + */ + getClusters(): Promise; +} diff --git a/yarn.lock b/yarn.lock index 8a7e8a1dac..0d8a47e589 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7673,6 +7673,7 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" + "@backstage/types": "workspace:^" languageName: unknown linkType: soft From 49e6285275167d4713e35d9409e9ec8ad3e63872 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Thu, 23 Nov 2023 10:44:44 -0500 Subject: [PATCH 2/7] Creating extension point for kubernetesAuthStrategy Signed-off-by: Andres Mauricio Gomez P --- plugins/kubernetes-backend/src/auth/types.ts | 38 --------------- plugins/kubernetes-backend/src/plugin.ts | 47 +++++++++++++++++-- .../src/service/KubernetesBuilder.ts | 6 ++- .../src/service/KubernetesFanOutHandler.ts | 5 +- .../src/service/KubernetesFetcher.ts | 6 ++- plugins/kubernetes-backend/src/types/types.ts | 12 ++++- plugins/kubernetes-node/src/extensions.ts | 20 ++++++++ plugins/kubernetes-node/src/index.ts | 2 + plugins/kubernetes-node/src/types/types.ts | 20 ++++++++ 9 files changed, 107 insertions(+), 49 deletions(-) delete mode 100644 plugins/kubernetes-backend/src/auth/types.ts diff --git a/plugins/kubernetes-backend/src/auth/types.ts b/plugins/kubernetes-backend/src/auth/types.ts deleted file mode 100644 index fff9952bae..0000000000 --- a/plugins/kubernetes-backend/src/auth/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthMetadata, ClusterDetails } from '../types/types'; -import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; - -/** - * Authentication data used to make a request to Kubernetes - * @public - */ -export type KubernetesCredential = - | { type: 'bearer token'; token: string } - | { type: 'anonymous' }; - -/** - * - * @public - */ -export interface AuthenticationStrategy { - getCredential( - clusterDetails: ClusterDetails, - authConfig: KubernetesRequestAuth, - ): Promise; - validateCluster(authMetadata: AuthMetadata): Error[]; -} diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index 2d5f1e1d46..e93e8c5700 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -29,6 +29,9 @@ import { KubernetesClusterSupplierExtensionPoint, kubernetesClusterSupplierExtensionPoint, KubernetesClustersSupplier, + KubernetesAuthStrategyExtensionPoint, + AuthenticationStrategy, + kubernetesAuthStrategyExtensionPoint, } from '@backstage/plugin-kubernetes-node'; class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { @@ -65,6 +68,35 @@ class ClusterSuplier implements KubernetesClusterSupplierExtensionPoint { } } +class AuthStrategy implements KubernetesAuthStrategyExtensionPoint { + private authStrategies: Array<{ + key: string; + strategy: AuthenticationStrategy; + }>; + + constructor() { + this.authStrategies = new Array<{ + key: string; + strategy: AuthenticationStrategy; + }>(); + } + + static addAuthStrategiesFromArray( + authStrategies: Array<{ key: string; strategy: AuthenticationStrategy }>, + builder: KubernetesBuilder, + ) { + authStrategies.forEach(st => builder.addAuthStrategy(st.key, st.strategy)); + } + + getAuthenticationStrategies() { + return this.authStrategies; + } + + addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) { + this.authStrategies.push({ key, strategy: authStrategy }); + } +} + /** * This is the backend plugin that provides the Kubernetes integration. * @alpha @@ -75,6 +107,7 @@ export const kubernetesPlugin = createBackendPlugin({ register(env) { const extPointObjectsProvider = new ObjectsProvider(); const extPointClusterSuplier = new ClusterSuplier(); + const extPointAuthStrategy = new AuthStrategy(); env.registerExtensionPoint( kubernetesObjectsProviderExtensionPoint, extPointObjectsProvider, @@ -83,6 +116,10 @@ export const kubernetesPlugin = createBackendPlugin({ kubernetesClusterSupplierExtensionPoint, extPointClusterSuplier, ); + env.registerExtensionPoint( + kubernetesAuthStrategyExtensionPoint, + extPointAuthStrategy, + ); env.registerInit({ deps: { @@ -95,15 +132,19 @@ export const kubernetesPlugin = createBackendPlugin({ async init({ http, logger, config, catalogApi, permissions }) { const winstonLogger = loggerToWinstonLogger(logger); // TODO: expose all of the customization & extension points of the builder here - const { router } = await KubernetesBuilder.createBuilder({ + const builder: KubernetesBuilder = KubernetesBuilder.createBuilder({ logger: winstonLogger, config, catalogApi, permissions, }) .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) - .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) - .build(); + .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()); + AuthStrategy.addAuthStrategiesFromArray( + extPointAuthStrategy.getAuthenticationStrategies(), + builder, + ); + const { router } = await builder.build(); http.use(router); }, }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 3bc7402179..c1ff4688e7 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -46,7 +46,6 @@ import { MultiTenantServiceLocator } from '../service-locator/MultiTenantService import { SingleTenantServiceLocator } from '../service-locator/SingleTenantServiceLocator'; import { CustomResource, - KubernetesClustersSupplier, KubernetesFetcher, KubernetesObjectsProviderOptions, KubernetesObjectTypes, @@ -54,7 +53,10 @@ import { ObjectsByEntityRequest, ServiceLocatorMethod, } from '../types/types'; -import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; +import { + KubernetesClustersSupplier, + KubernetesObjectsProvider, +} from '@backstage/plugin-kubernetes-node'; import { DEFAULT_OBJECTS, KubernetesFanOutHandler, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 3ea06e061e..7a8ff1bf2d 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -17,7 +17,6 @@ import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; import { - ClusterDetails, KubernetesFetcher, KubernetesObjectsProviderOptions, KubernetesServiceLocator, @@ -26,7 +25,6 @@ import { ObjectToFetch, CustomResource, } from '../types/types'; -import { AuthenticationStrategy, KubernetesCredential } from '../auth/types'; import { ClientContainerStatus, ClientCurrentResourceUsage, @@ -45,7 +43,10 @@ import { PodStatus, } from '@kubernetes/client-node'; import { + AuthenticationStrategy, + ClusterDetails, CustomResourcesByEntity, + KubernetesCredential, KubernetesObjectsByEntity, } from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index d5c945a864..99501c48c6 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -26,12 +26,10 @@ import { import lodash, { Dictionary } from 'lodash'; import { Logger } from 'winston'; import { - ClusterDetails, FetchResponseWrapper, KubernetesFetcher, ObjectFetchParams, } from '../types/types'; -import { KubernetesCredential } from '../auth/types'; import { ANNOTATION_KUBERNETES_AUTH_PROVIDER, FetchResponse, @@ -43,6 +41,10 @@ import fetch, { RequestInit, Response } from 'node-fetch'; import * as https from 'https'; import fs from 'fs-extra'; import { JsonObject } from '@backstage/types'; +import { + ClusterDetails, + KubernetesCredential, +} from '@backstage/plugin-kubernetes-node'; export interface KubernetesClientBasedFetcherOptions { logger: Logger; diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index a4bd38802b..c64a2b7863 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -23,8 +23,10 @@ import type { KubernetesRequestBody, } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; -import { KubernetesCredential } from '../auth/types'; -import { ClusterDetails } from '@backstage/plugin-kubernetes-node'; +import { + ClusterDetails, + KubernetesCredential, +} from '@backstage/plugin-kubernetes-node'; /** * @@ -150,3 +152,9 @@ export interface KubernetesObjectsProviderOptions { * @public */ export type ObjectsByEntityRequest = KubernetesRequestBody; + +export type { + AuthMetadata, + ClusterDetails, + KubernetesClustersSupplier, +} from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts index 3975fa65c3..3c110be348 100644 --- a/plugins/kubernetes-node/src/extensions.ts +++ b/plugins/kubernetes-node/src/extensions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; @@ -54,3 +55,22 @@ export const kubernetesClusterSupplierExtensionPoint = createExtensionPoint({ id: 'kubernetes.cluster-supplier', }); + +/** + * The interface for {@link kubernetesAuthStrategyExtensionPoint}. + * + * @public + */ +export interface KubernetesAuthStrategyExtensionPoint { + addAuthStrategy(key: string, strategy: AuthenticationStrategy): void; +} + +/** + * An extension point the exposes the ability to add an Auth Strategy. + * + * @public + */ +export const kubernetesAuthStrategyExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.auth-strategy', + }); diff --git a/plugins/kubernetes-node/src/index.ts b/plugins/kubernetes-node/src/index.ts index a3da594b43..63a478593c 100644 --- a/plugins/kubernetes-node/src/index.ts +++ b/plugins/kubernetes-node/src/index.ts @@ -34,6 +34,8 @@ export { type KubernetesObjectsProviderExtensionPoint, kubernetesClusterSupplierExtensionPoint, type KubernetesClusterSupplierExtensionPoint, + kubernetesAuthStrategyExtensionPoint, + type KubernetesAuthStrategyExtensionPoint, } from './extensions'; export * from './types'; diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index f9f60b7085..dfc0395bc4 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -130,3 +130,23 @@ export interface KubernetesClustersSupplier { */ getClusters(): Promise; } + +/** + * Authentication data used to make a request to Kubernetes + * @public + */ +export type KubernetesCredential = + | { type: 'bearer token'; token: string } + | { type: 'anonymous' }; + +/** + * + * @public + */ +export interface AuthenticationStrategy { + getCredential( + clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, + ): Promise; + validateCluster(authMetadata: AuthMetadata): Error[]; +} From aa8ee8559b4b256176651d94c2423cda74c875f5 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Mon, 27 Nov 2023 09:18:11 -0500 Subject: [PATCH 3/7] Creating extension point for kubernetesFetcher Signed-off-by: Andres Mauricio Gomez P --- plugins/kubernetes-backend/package.json | 2 + plugins/kubernetes-backend/src/plugin.ts | 30 +++++++- plugins/kubernetes-backend/src/types/types.ts | 70 +++---------------- plugins/kubernetes-node/package.json | 1 + plugins/kubernetes-node/src/extensions.ts | 20 ++++++ plugins/kubernetes-node/src/index.ts | 10 +-- plugins/kubernetes-node/src/types/types.ts | 62 ++++++++++++++++ 7 files changed, 123 insertions(+), 72 deletions(-) diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 64f308b74c..8a0a5cbefb 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -90,6 +90,8 @@ "@backstage/backend-app-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/plugin-permission-backend": "workspace:^", + "@backstage/plugin-permission-backend-module-allow-all-policy": "workspace:^", "@types/aws4": "^1.5.1", "msw": "^1.0.0", "supertest": "^6.1.3", diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index e93e8c5700..8fdef794d1 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -32,6 +32,11 @@ import { KubernetesAuthStrategyExtensionPoint, AuthenticationStrategy, kubernetesAuthStrategyExtensionPoint, + KubernetesFetcher, +} from '@backstage/plugin-kubernetes-node'; +import { + KubernetesFetcherExtensionPoint, + kubernetesFetcherExtensionPoint, } from '@backstage/plugin-kubernetes-node'; class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { @@ -68,6 +73,23 @@ class ClusterSuplier implements KubernetesClusterSupplierExtensionPoint { } } +class Fetcher implements KubernetesFetcherExtensionPoint { + private fetcher: KubernetesFetcher | undefined; + + getFetcher() { + return this.fetcher; + } + + addFetcher(fetcher: KubernetesFetcher) { + if (this.fetcher) { + throw new Error( + 'Multiple Kubernetes Fetchers is not supported at this time', + ); + } + this.fetcher = fetcher; + } +} + class AuthStrategy implements KubernetesAuthStrategyExtensionPoint { private authStrategies: Array<{ key: string; @@ -108,6 +130,7 @@ export const kubernetesPlugin = createBackendPlugin({ const extPointObjectsProvider = new ObjectsProvider(); const extPointClusterSuplier = new ClusterSuplier(); const extPointAuthStrategy = new AuthStrategy(); + const extPointFetcher = new Fetcher(); env.registerExtensionPoint( kubernetesObjectsProviderExtensionPoint, extPointObjectsProvider, @@ -120,6 +143,10 @@ export const kubernetesPlugin = createBackendPlugin({ kubernetesAuthStrategyExtensionPoint, extPointAuthStrategy, ); + env.registerExtensionPoint( + kubernetesFetcherExtensionPoint, + extPointFetcher, + ); env.registerInit({ deps: { @@ -139,7 +166,8 @@ export const kubernetesPlugin = createBackendPlugin({ permissions, }) .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) - .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()); + .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) + .setFetcher(extPointFetcher.getFetcher()); AuthStrategy.addAuthStrategiesFromArray( extPointAuthStrategy.getAuthenticationStrategies(), builder, diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index c64a2b7863..f980821c4d 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -18,75 +18,16 @@ import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; import type { CustomResourceMatcher, - FetchResponse, - KubernetesFetchError, KubernetesRequestBody, } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; import { ClusterDetails, - KubernetesCredential, + CustomResource, + KubernetesFetcher, + ObjectToFetch, } from '@backstage/plugin-kubernetes-node'; -/** - * - * @public - */ -export interface ObjectFetchParams { - serviceId: string; - clusterDetails: ClusterDetails; - credential: KubernetesCredential; - objectTypesToFetch: Set; - labelSelector?: string; - customResources: CustomResource[]; - namespace?: string; -} - -/** - * Fetches information from a kubernetes cluster using the cluster details object to target a specific cluster - * - * @public - */ -export interface KubernetesFetcher { - fetchObjectsForService( - params: ObjectFetchParams, - ): Promise; - fetchPodMetricsByNamespaces( - clusterDetails: ClusterDetails, - credential: KubernetesCredential, - namespaces: Set, - labelSelector?: string, - ): Promise; -} - -/** - * - * @public - */ -export interface FetchResponseWrapper { - errors: KubernetesFetchError[]; - responses: FetchResponse[]; -} - -/** - * - * @public - */ -export interface ObjectToFetch { - objectType: KubernetesObjectTypes; - group: string; - apiVersion: string; - plural: string; -} - -/** - * - * @public - */ -export interface CustomResource extends ObjectToFetch { - objectType: 'customresources'; -} - /** * * @public @@ -157,4 +98,9 @@ export type { AuthMetadata, ClusterDetails, KubernetesClustersSupplier, + ObjectToFetch, + CustomResource, + ObjectFetchParams, + FetchResponseWrapper, + KubernetesFetcher, } from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 56f4ba01c4..37922fc2e9 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -30,6 +30,7 @@ "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", + "@backstage/plugin-kubernetes-backend": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/types": "workspace:^" } diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts index 3c110be348..0c6107ee46 100644 --- a/plugins/kubernetes-node/src/extensions.ts +++ b/plugins/kubernetes-node/src/extensions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { KubernetesFetcher } from '@backstage/plugin-kubernetes-backend'; import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; @@ -74,3 +75,22 @@ export const kubernetesAuthStrategyExtensionPoint = createExtensionPoint({ id: 'kubernetes.auth-strategy', }); + +/** + * The interface for {@link kubernetesFetcherExtensionPoint}. + * + * @public + */ +export interface KubernetesFetcherExtensionPoint { + addFetcher(fetcher: KubernetesFetcher): void; +} + +/** + * An extension point the exposes the ability to configure a kubernetes fetcher. + * + * @public + */ +export const kubernetesFetcherExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.fetcher', + }); diff --git a/plugins/kubernetes-node/src/index.ts b/plugins/kubernetes-node/src/index.ts index 63a478593c..162d5baf26 100644 --- a/plugins/kubernetes-node/src/index.ts +++ b/plugins/kubernetes-node/src/index.ts @@ -29,13 +29,5 @@ * @packageDocumentation */ -export { - kubernetesObjectsProviderExtensionPoint, - type KubernetesObjectsProviderExtensionPoint, - kubernetesClusterSupplierExtensionPoint, - type KubernetesClusterSupplierExtensionPoint, - kubernetesAuthStrategyExtensionPoint, - type KubernetesAuthStrategyExtensionPoint, -} from './extensions'; - +export * from './extensions'; export * from './types'; diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index dfc0395bc4..39fcd18ad0 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -14,8 +14,11 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; +import { KubernetesObjectTypes } from '@backstage/plugin-kubernetes-backend'; import { CustomResourceMatcher, + FetchResponse, + KubernetesFetchError, KubernetesRequestAuth, ObjectsByEntityResponse, } from '@backstage/plugin-kubernetes-common'; @@ -150,3 +153,62 @@ export interface AuthenticationStrategy { ): Promise; validateCluster(authMetadata: AuthMetadata): Error[]; } + +/** + * + * @public + */ +export interface ObjectToFetch { + objectType: KubernetesObjectTypes; // TODO - Review + group: string; + apiVersion: string; + plural: string; +} + +/** + * + * @public + */ +export interface CustomResource extends ObjectToFetch { + objectType: 'customresources'; +} + +/** + * + * @public + */ +export interface ObjectFetchParams { + serviceId: string; + clusterDetails: ClusterDetails; + credential: KubernetesCredential; + objectTypesToFetch: Set; + labelSelector?: string; + customResources: CustomResource[]; + namespace?: string; +} + +/** + * + * @public + */ +export interface FetchResponseWrapper { + errors: KubernetesFetchError[]; + responses: FetchResponse[]; +} + +/** + * Fetches information from a kubernetes cluster using the cluster details object to target a specific cluster + * + * @public + */ +export interface KubernetesFetcher { + fetchObjectsForService( + params: ObjectFetchParams, + ): Promise; + fetchPodMetricsByNamespaces( + clusterDetails: ClusterDetails, + credential: KubernetesCredential, + namespaces: Set, + labelSelector?: string, + ): Promise; +} From 673e08a1a3d475f2213d771e4439969a29e78a5d Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Mon, 27 Nov 2023 09:51:32 -0500 Subject: [PATCH 4/7] Creating extension point for kubernetesServiceLocator Signed-off-by: Andres Mauricio Gomez P --- plugins/kubernetes-backend/src/auth/types.ts | 20 ++++++++++ plugins/kubernetes-backend/src/plugin.ts | 30 ++++++++++++++- plugins/kubernetes-backend/src/types/types.ts | 38 ++----------------- plugins/kubernetes-node/src/extensions.ts | 30 +++++++++++++-- plugins/kubernetes-node/src/types/types.ts | 18 +++++++++ yarn.lock | 3 ++ 6 files changed, 99 insertions(+), 40 deletions(-) create mode 100644 plugins/kubernetes-backend/src/auth/types.ts diff --git a/plugins/kubernetes-backend/src/auth/types.ts b/plugins/kubernetes-backend/src/auth/types.ts new file mode 100644 index 0000000000..611835048b --- /dev/null +++ b/plugins/kubernetes-backend/src/auth/types.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type { + AuthenticationStrategy, + KubernetesCredential, +} from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index 8fdef794d1..1b4aca4160 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -33,6 +33,9 @@ import { AuthenticationStrategy, kubernetesAuthStrategyExtensionPoint, KubernetesFetcher, + KubernetesServiceLocatorExtensionPoint, + KubernetesServiceLocator, + kubernetesServiceLocatorExtensionPoint, } from '@backstage/plugin-kubernetes-node'; import { KubernetesFetcherExtensionPoint, @@ -90,6 +93,23 @@ class Fetcher implements KubernetesFetcherExtensionPoint { } } +class ServiceLocator implements KubernetesServiceLocatorExtensionPoint { + private serviceLocator: KubernetesServiceLocator | undefined; + + getServiceLocator() { + return this.serviceLocator; + } + + addServiceLocator(serviceLocator: KubernetesServiceLocator) { + if (this.serviceLocator) { + throw new Error( + 'Multiple Kubernetes Service Locators is not supported at this time', + ); + } + this.serviceLocator = serviceLocator; + } +} + class AuthStrategy implements KubernetesAuthStrategyExtensionPoint { private authStrategies: Array<{ key: string; @@ -131,6 +151,8 @@ export const kubernetesPlugin = createBackendPlugin({ const extPointClusterSuplier = new ClusterSuplier(); const extPointAuthStrategy = new AuthStrategy(); const extPointFetcher = new Fetcher(); + const extPointServiceLocator = new ServiceLocator(); + env.registerExtensionPoint( kubernetesObjectsProviderExtensionPoint, extPointObjectsProvider, @@ -147,6 +169,10 @@ export const kubernetesPlugin = createBackendPlugin({ kubernetesFetcherExtensionPoint, extPointFetcher, ); + env.registerExtensionPoint( + kubernetesServiceLocatorExtensionPoint, + extPointServiceLocator, + ); env.registerInit({ deps: { @@ -167,7 +193,9 @@ export const kubernetesPlugin = createBackendPlugin({ }) .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) - .setFetcher(extPointFetcher.getFetcher()); + .setFetcher(extPointFetcher.getFetcher()) + .setServiceLocator(extPointServiceLocator.getServiceLocator()); + AuthStrategy.addAuthStrategiesFromArray( extPointAuthStrategy.getAuthenticationStrategies(), builder, diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index f980821c4d..fade501417 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -14,17 +14,13 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; -import type { - CustomResourceMatcher, - KubernetesRequestBody, -} from '@backstage/plugin-kubernetes-common'; +import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; import { - ClusterDetails, CustomResource, KubernetesFetcher, + KubernetesServiceLocator, ObjectToFetch, } from '@backstage/plugin-kubernetes-node'; @@ -50,25 +46,6 @@ export type KubernetesObjectTypes = // If updating this list, also make sure to update // `objectTypes` and `apiVersionOverrides` in config.d.ts! -/** - * @public - */ -export interface ServiceLocatorRequestContext { - objectTypesToFetch: Set; - customResources: CustomResourceMatcher[]; -} - -/** - * Used to locate which cluster(s) a service is running on - * @public - */ -export interface KubernetesServiceLocator { - getClustersByEntity( - entity: Entity, - requestContext: ServiceLocatorRequestContext, - ): Promise<{ clusters: ClusterDetails[] }>; -} - /** * * @public @@ -94,13 +71,4 @@ export interface KubernetesObjectsProviderOptions { */ export type ObjectsByEntityRequest = KubernetesRequestBody; -export type { - AuthMetadata, - ClusterDetails, - KubernetesClustersSupplier, - ObjectToFetch, - CustomResource, - ObjectFetchParams, - FetchResponseWrapper, - KubernetesFetcher, -} from '@backstage/plugin-kubernetes-node'; +export type * from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts index 0c6107ee46..d898244161 100644 --- a/plugins/kubernetes-node/src/extensions.ts +++ b/plugins/kubernetes-node/src/extensions.ts @@ -14,10 +14,13 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; -import { KubernetesFetcher } from '@backstage/plugin-kubernetes-backend'; -import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; -import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; -import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; +import { + AuthenticationStrategy, + KubernetesClustersSupplier, + KubernetesFetcher, + KubernetesObjectsProvider, + KubernetesServiceLocator, +} from '@backstage/plugin-kubernetes-node'; /** * The interface for {@link kubernetesObjectsProviderExtensionPoint}. @@ -94,3 +97,22 @@ export const kubernetesFetcherExtensionPoint = createExtensionPoint({ id: 'kubernetes.fetcher', }); + +/** + * The interface for {@link kubernetesServiceLocatorExtensionPoint}. + * + * @public + */ +export interface KubernetesServiceLocatorExtensionPoint { + addServiceLocator(serviceLocator: KubernetesServiceLocator): void; +} + +/** + * An extension point the exposes the ability to configure a kubernetes service locator. + * + * @public + */ +export const kubernetesServiceLocatorExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.service-locator', + }); diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index 39fcd18ad0..59582bc0f2 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -212,3 +212,21 @@ export interface KubernetesFetcher { labelSelector?: string, ): Promise; } +/** + * @public + */ +export interface ServiceLocatorRequestContext { + objectTypesToFetch: Set; + customResources: CustomResourceMatcher[]; +} + +/** + * Used to locate which cluster(s) a service is running on + * @public + */ +export interface KubernetesServiceLocator { + getClustersByEntity( + entity: Entity, + requestContext: ServiceLocatorRequestContext, + ): Promise<{ clusters: ClusterDetails[] }>; +} diff --git a/yarn.lock b/yarn.lock index 0d8a47e589..71aa0872c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7574,6 +7574,8 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" "@backstage/plugin-kubernetes-node": "workspace:^" + "@backstage/plugin-permission-backend": "workspace:^" + "@backstage/plugin-permission-backend-module-allow-all-policy": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" @@ -7672,6 +7674,7 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/plugin-kubernetes-backend": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" "@backstage/types": "workspace:^" languageName: unknown From 6c5d7f6f4041fd2805de6de9d06db272fd740aef Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Mon, 27 Nov 2023 09:53:10 -0500 Subject: [PATCH 5/7] Refactoring KubernetesBuilder.test.ts to use kubernetesObjectsProviderExtensionPoint, kubernetesClusterSupplierExtensionPoint, kubernetesAuthStrategyExtensionPoint, kubernetesFetcherExtensionPoint and kubernetesServiceLocatorExtensionPoint Signed-off-by: Andres Mauricio Gomez P --- .changeset/plenty-falcons-travel.md | 8 +- plugins/kubernetes-backend/api-report.md | 160 +---- plugins/kubernetes-backend/src/auth/types.ts | 2 + .../src/service/KubernetesBuilder.test.ts | 666 ++++++++++++------ plugins/kubernetes-backend/src/types/types.ts | 23 +- plugins/kubernetes-node/api-report.md | 187 +++++ plugins/kubernetes-node/package.json | 1 - plugins/kubernetes-node/src/types/types.ts | 23 +- yarn.lock | 1 - 9 files changed, 678 insertions(+), 393 deletions(-) diff --git a/.changeset/plenty-falcons-travel.md b/.changeset/plenty-falcons-travel.md index cfc3ffd6f5..0c8706cde0 100644 --- a/.changeset/plenty-falcons-travel.md +++ b/.changeset/plenty-falcons-travel.md @@ -3,4 +3,10 @@ '@backstage/plugin-kubernetes-backend': patch --- -The `kubernetes-node` plugin has been modified to house a new extension points for Kubernetes backend plugin; `KubernetesClusterSupplierExtensionPoint` is introduced . The `kubernetes-backend` plugin was modified to use this new extension point. +The `kubernetes-node` plugin has been modified to house a new extension points for Kubernetes backend plugin; +`KubernetesClusterSupplierExtensionPoint` is introduced . +`kubernetesAuthStrategyExtensionPoint` is introduced . +`kubernetesFetcherExtensionPoint` is introduced . +`kubernetesServiceLocatorExtensionPoint` is introduced . + +The `kubernetes-backend` plugin was modified to use this new extension point. diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index f79b14ede0..04c7cf8b1e 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -3,21 +3,25 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; +import { AuthMetadata } from '@backstage/plugin-kubernetes-node'; import { CatalogApi } from '@backstage/catalog-client'; +import { ClusterDetails } from '@backstage/plugin-kubernetes-node'; import { Config } from '@backstage/config'; -import type { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; +import { CustomResource } from '@backstage/plugin-kubernetes-node'; import { CustomResourcesByEntity } from '@backstage/plugin-kubernetes-node'; import { Duration } from 'luxon'; -import { Entity } from '@backstage/catalog-model'; import express from 'express'; -import type { FetchResponse } from '@backstage/plugin-kubernetes-common'; -import type { JsonObject } from '@backstage/types'; -import type { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; +import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; +import { KubernetesCredential } from '@backstage/plugin-kubernetes-node'; +import { KubernetesFetcher } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsByEntity } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; +import { KubernetesServiceLocator } from '@backstage/plugin-kubernetes-node'; import { Logger } from 'winston'; +import { ObjectToFetch } from '@backstage/plugin-kubernetes-node'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RequestHandler } from 'http-proxy-middleware'; @@ -42,19 +46,9 @@ export class AnonymousStrategy implements AuthenticationStrategy { validateCluster(): Error[]; } -// @public (undocumented) -export interface AuthenticationStrategy { - // (undocumented) - getCredential( - clusterDetails: ClusterDetails, - authConfig: KubernetesRequestAuth, - ): Promise; - // (undocumented) - validateCluster(authMetadata: AuthMetadata): Error[]; -} +export { AuthenticationStrategy }; -// @public -export type AuthMetadata = Record; +export { AuthMetadata }; // @public (undocumented) export class AwsIamStrategy implements AuthenticationStrategy { @@ -74,35 +68,11 @@ export class AzureIdentityStrategy implements AuthenticationStrategy { validateCluster(): Error[]; } -// @public (undocumented) -export interface ClusterDetails { - // (undocumented) - authMetadata: AuthMetadata; - // (undocumented) - caData?: string | undefined; - // (undocumented) - caFile?: string | undefined; - customResources?: CustomResourceMatcher[]; - dashboardApp?: string; - dashboardParameters?: JsonObject; - dashboardUrl?: string; - name: string; - skipMetricsLookup?: boolean; - // (undocumented) - skipTLSVerify?: boolean; - // (undocumented) - url: string; -} +export { ClusterDetails }; // @public @deprecated export function createRouter(options: RouterOptions): Promise; -// @public (undocumented) -export interface CustomResource extends ObjectToFetch { - // (undocumented) - objectType: 'customresources'; -} - export { CustomResourcesByEntity }; // @public (undocumented) @@ -127,14 +97,6 @@ export type DispatchStrategyOptions = { }; }; -// @public (undocumented) -export interface FetchResponseWrapper { - // (undocumented) - errors: KubernetesFetchError[]; - // (undocumented) - responses: FetchResponse[]; -} - // @public (undocumented) export class GoogleServiceAccountStrategy implements AuthenticationStrategy { // (undocumented) @@ -276,20 +238,9 @@ export type KubernetesBuilderReturn = Promise<{ }; }>; -// @public -export interface KubernetesClustersSupplier { - getClusters(): Promise; -} +export { KubernetesClustersSupplier }; -// @public -export type KubernetesCredential = - | { - type: 'bearer token'; - token: string; - } - | { - type: 'anonymous'; - }; +export { KubernetesCredential }; // @public (undocumented) export interface KubernetesEnvironment { @@ -303,21 +254,6 @@ export interface KubernetesEnvironment { permissions: PermissionEvaluator; } -// @public -export interface KubernetesFetcher { - // (undocumented) - fetchObjectsForService( - params: ObjectFetchParams, - ): Promise; - // (undocumented) - fetchPodMetricsByNamespaces( - clusterDetails: ClusterDetails, - credential: KubernetesCredential, - namespaces: Set, - labelSelector?: string, - ): Promise; -} - export { KubernetesObjectsByEntity }; export { KubernetesObjectsProvider }; @@ -338,23 +274,6 @@ export interface KubernetesObjectsProviderOptions { serviceLocator: KubernetesServiceLocator; } -// @public (undocumented) -export type KubernetesObjectTypes = - | 'pods' - | 'services' - | 'configmaps' - | 'deployments' - | 'limitranges' - | 'resourcequotas' - | 'replicasets' - | 'horizontalpodautoscalers' - | 'jobs' - | 'cronjobs' - | 'ingresses' - | 'customresources' - | 'statefulsets' - | 'daemonsets'; - // @public export class KubernetesProxy { constructor(options: KubernetesProxyOptions); @@ -376,50 +295,9 @@ export type KubernetesProxyOptions = { authStrategy: AuthenticationStrategy; }; -// @public -export interface KubernetesServiceLocator { - // (undocumented) - getClustersByEntity( - entity: Entity, - requestContext: ServiceLocatorRequestContext, - ): Promise<{ - clusters: ClusterDetails[]; - }>; -} - -// @public (undocumented) -export interface ObjectFetchParams { - // (undocumented) - clusterDetails: ClusterDetails; - // (undocumented) - credential: KubernetesCredential; - // (undocumented) - customResources: CustomResource[]; - // (undocumented) - labelSelector?: string; - // (undocumented) - namespace?: string; - // (undocumented) - objectTypesToFetch: Set; - // (undocumented) - serviceId: string; -} - // @public (undocumented) export type ObjectsByEntityRequest = KubernetesRequestBody; -// @public (undocumented) -export interface ObjectToFetch { - // (undocumented) - apiVersion: string; - // (undocumented) - group: string; - // (undocumented) - objectType: KubernetesObjectTypes; - // (undocumented) - plural: string; -} - // @public (undocumented) export class OidcStrategy implements AuthenticationStrategy { // (undocumented) @@ -458,18 +336,12 @@ export class ServiceAccountStrategy implements AuthenticationStrategy { // @public (undocumented) export type ServiceLocatorMethod = 'multiTenant' | 'singleTenant' | 'http'; -// @public (undocumented) -export interface ServiceLocatorRequestContext { - // (undocumented) - customResources: CustomResourceMatcher[]; - // (undocumented) - objectTypesToFetch: Set; -} - // @public (undocumented) export type SigningCreds = { accessKeyId: string | undefined; secretAccessKey: string | undefined; sessionToken: string | undefined; }; + +export * from '@backstage/plugin-kubernetes-node'; ``` diff --git a/plugins/kubernetes-backend/src/auth/types.ts b/plugins/kubernetes-backend/src/auth/types.ts index 611835048b..c7d60e8f2b 100644 --- a/plugins/kubernetes-backend/src/auth/types.ts +++ b/plugins/kubernetes-backend/src/auth/types.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +// TODO remove this re-export as a breaking change after a couple of releases + export type { AuthenticationStrategy, KubernetesCredential, diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index c676cc6246..77d02a032a 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -14,106 +14,181 @@ * limitations under the License. */ -import { getVoidLogger } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; -import { Config, ConfigReader } from '@backstage/config'; import { ANNOTATION_KUBERNETES_AUTH_PROVIDER, ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER, ObjectsByEntityResponse, KubernetesRequestAuth, } from '@backstage/plugin-kubernetes-common'; -import express from 'express'; import request from 'supertest'; import { ClusterDetails, FetchResponseWrapper, - KubernetesClustersSupplier, KubernetesFetcher, KubernetesServiceLocator, ObjectFetchParams, } from '../types/types'; import { KubernetesCredential } from '../auth/types'; -import { KubernetesBuilder } from './KubernetesBuilder'; -import { KubernetesFanOutHandler } from './KubernetesFanOutHandler'; -import { CatalogApi } from '@backstage/catalog-client'; import { HEADER_KUBERNETES_CLUSTER, HEADER_KUBERNETES_AUTH, } from './KubernetesProxy'; import { setupServer } from 'msw/node'; -import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { + ServiceMock, + mockServices, + setupRequestMockHandlers, + startTestBackend, +} from '@backstage/backend-test-utils'; import { rest } from 'msw'; import { AuthorizeResult, PermissionEvaluator, } from '@backstage/plugin-permission-common'; +import { + PermissionsService, + createBackendModule, +} from '@backstage/backend-plugin-api'; +import { + KubernetesObjectsProvider, + kubernetesAuthStrategyExtensionPoint, + kubernetesClusterSupplierExtensionPoint, + kubernetesObjectsProviderExtensionPoint, + kubernetesFetcherExtensionPoint, + kubernetesServiceLocatorExtensionPoint, +} from '@backstage/plugin-kubernetes-node'; +import { ExtendedHttpServer } from '@backstage/backend-app-api'; describe('KubernetesBuilder', () => { - let app: express.Express; - let kubernetesFanOutHandler: jest.Mocked; - let config: Config; - let catalogApi: CatalogApi; - let permissions: jest.Mocked; + let app: ExtendedHttpServer; + let objectsProviderMock: KubernetesObjectsProvider; + const happyK8SResult = { + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + } as any; + const policyMock: jest.Mocked = { + authorize: jest.fn(), + authorizeConditional: jest.fn(), + }; + const permissionsMock: ServiceMock = + mockServices.permissions.mock(policyMock); beforeEach(async () => { jest.resetAllMocks(); - const logger = getVoidLogger(); - config = new ConfigReader({ - kubernetes: { - serviceLocatorMethod: { type: 'multiTenant' }, - clusterLocatorMethods: [{ type: 'config', clusters: [] }], - }, + + objectsProviderMock = { + getKubernetesObjectsByEntity: jest.fn().mockImplementation(_ => { + return Promise.resolve(happyK8SResult); + }), + getCustomResourcesByEntity: jest.fn().mockImplementation(_ => { + return Promise.resolve(happyK8SResult); + }), + }; + + const clusterSupplierMock = { + getClusters: jest.fn().mockImplementation(_ => { + return Promise.resolve([ + { + name: 'some-cluster', + url: 'https://localhost:1234', + authMetadata: { + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'serviceAccount', + }, + }, + { + name: 'some-other-cluster', + url: 'https://localhost:1235', + authMetadata: { + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'oidc', + [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google', + }, + }, + ]); + }), + }; + + jest.mock('@backstage/catalog-client', () => ({ + CatalogClient: jest.fn().mockImplementation(() => ({ + getEntityByRef: jest.fn().mockImplementation(entityRef => { + if (entityRef.name === 'noentity') { + return Promise.resolve(undefined); + } + return Promise.resolve({ + kind: entityRef.kind, + metadata: { + name: entityRef.name, + namespace: entityRef.namespace, + }, + } as Entity); + }), + })), + })); + + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', + }, + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, + }), + import('@backstage/plugin-kubernetes-backend/alpha'), + import('@backstage/plugin-permission-backend/alpha'), + import('@backstage/plugin-permission-backend-module-allow-all-policy'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testObjectsProvider', + register(env) { + env.registerInit({ + deps: { extension: kubernetesObjectsProviderExtensionPoint }, + async init({ extension }) { + extension.addObjectsProvider(objectsProviderMock); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testClusterSupplier', + register(env) { + env.registerInit({ + deps: { extension: kubernetesClusterSupplierExtensionPoint }, + async init({ extension }) { + extension.addClusterSupplier(clusterSupplierMock); + }, + }); + }, + }), + ], }); - const clusters: ClusterDetails[] = [ - { - name: 'some-cluster', - url: 'https://localhost:1234', - authMetadata: { - [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'serviceAccount', - }, - }, - { - name: 'some-other-cluster', - url: 'https://localhost:1235', - authMetadata: { - [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'oidc', - [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google', - }, - }, - ]; - const clusterSupplier: KubernetesClustersSupplier = { - async getClusters() { - return clusters; - }, - }; - - kubernetesFanOutHandler = { - getKubernetesObjectsByEntity: jest.fn(), - } as any; - - permissions = { - authorize: jest.fn(), - authorizeConditional: jest.fn(), - }; - - const { router } = await KubernetesBuilder.createBuilder({ - config, - logger, - catalogApi, - permissions, - }) - .setObjectsProvider(kubernetesFanOutHandler) - .setClusterSupplier(clusterSupplier) - .build(); - - app = express().use(router); + app = server; }); describe('get /clusters', () => { it('happy path: lists clusters', async () => { - const response = await request(app).get('/clusters'); + const response = await request(app).get('/api/kubernetes/clusters'); expect(response.status).toEqual(200); expect(response.body).toStrictEqual({ @@ -133,70 +208,41 @@ describe('KubernetesBuilder', () => { }); describe('post /services/:serviceId', () => { it('happy path: lists kubernetes objects without auth in request body', async () => { - const result = { - clusterOne: { - pods: [ - { - metadata: { - name: 'pod1', - }, - }, - ], - }, - } as any; - kubernetesFanOutHandler.getKubernetesObjectsByEntity.mockReturnValueOnce( - Promise.resolve(result), + const response = await request(app).post( + '/api/kubernetes/services/test-service', ); - - const response = await request(app).post('/services/test-service'); - expect(response.status).toEqual(200); - expect(response.body).toEqual(result); + expect(response.body).toEqual(happyK8SResult); }); it('happy path: lists kubernetes objects with auth in request body', async () => { - const result = { - clusterOne: { - pods: [ - { - metadata: { - name: 'pod1', - }, - }, - ], - }, - } as any; - kubernetesFanOutHandler.getKubernetesObjectsByEntity.mockReturnValueOnce( - Promise.resolve(result), - ); - const response = await request(app) - .post('/services/test-service') + .post('/api/kubernetes/services/test-service') .send({ auth: { google: 'google_token_123', }, }) .set('Content-Type', 'application/json'); - expect(response.status).toEqual(200); - expect(response.body).toEqual(result); + expect(response.body).toEqual(happyK8SResult); }); it('internal error: lists kubernetes objects', async () => { - kubernetesFanOutHandler.getKubernetesObjectsByEntity.mockRejectedValue( - Error('some internal error'), - ); + objectsProviderMock.getKubernetesObjectsByEntity = jest + .fn() + .mockRejectedValue(Error('some internal error')); - const response = await request(app).post('/services/test-service'); + const response = await request(app).post( + '/api/kubernetes/services/test-service', + ); expect(response.status).toEqual(500); expect(response.body).toEqual({ error: 'some internal error' }); }); it('custom service locator', async () => { - const logger = getVoidLogger(); - const someCluster: ClusterDetails = { + const someCluster = { name: 'some-cluster', url: 'https://localhost:1234', authMetadata: { @@ -212,11 +258,13 @@ describe('KubernetesBuilder', () => { authMetadata: { [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google' }, }, ]; - const clusterSupplier: KubernetesClustersSupplier = { - async getClusters() { - return clusters; - }, + + const clusterSupplierMock = { + getClusters: jest.fn().mockImplementation(_ => { + return Promise.resolve(clusters); + }), }; + const pod = { metadata: { name: 'pod1', @@ -240,7 +288,7 @@ describe('KubernetesBuilder', () => { ], }; - const serviceLocator: KubernetesServiceLocator = { + const mockServiceLocator: KubernetesServiceLocator = { getClustersByEntity( _entity: Entity, ): Promise<{ clusters: ClusterDetails[] }> { @@ -248,7 +296,7 @@ describe('KubernetesBuilder', () => { }, }; - const fetcher: KubernetesFetcher = { + const mockFetcher: KubernetesFetcher = { fetchPodMetricsByNamespaces( _clusterDetails: ClusterDetails, _credential: KubernetesCredential, @@ -271,20 +319,67 @@ describe('KubernetesBuilder', () => { }, }; - const { router } = await KubernetesBuilder.createBuilder({ - logger, - config, - catalogApi, - permissions, - }) - .setClusterSupplier(clusterSupplier) - .setServiceLocator(serviceLocator) - .setFetcher(fetcher) - .build(); - app = express().use(router); + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', + }, + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, + }), + import('@backstage/plugin-kubernetes-backend/alpha'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testClusterSupplier', + register(env) { + env.registerInit({ + deps: { extension: kubernetesClusterSupplierExtensionPoint }, + async init({ extension }) { + extension.addClusterSupplier(clusterSupplierMock); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testFetcher', + register(env) { + env.registerInit({ + deps: { extension: kubernetesFetcherExtensionPoint }, + async init({ extension }) { + extension.addFetcher(mockFetcher); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testServiceLocator', + register(env) { + env.registerInit({ + deps: { extension: kubernetesServiceLocatorExtensionPoint }, + async init({ extension }) { + extension.addServiceLocator(mockServiceLocator); + }, + }); + }, + }), + ], + }); + + app = server; const response = await request(app) - .post('/services/test-service') + .post('/api/kubernetes/services/test-service') .send({ entity: { metadata: { @@ -298,9 +393,6 @@ describe('KubernetesBuilder', () => { }); it('reads auth data for custom strategy', async () => { - permissions.authorize.mockResolvedValue([ - { result: AuthorizeResult.ALLOW }, - ]); const mockFetcher = { fetchPodMetricsByNamespaces: jest .fn() @@ -312,43 +404,93 @@ describe('KubernetesBuilder', () => { ], }), }; - const { router } = await KubernetesBuilder.createBuilder({ - logger: getVoidLogger(), - config, - catalogApi, - permissions, - }) - .addAuthStrategy('custom', { - getCredential: jest - .fn< - Promise, - [ClusterDetails, KubernetesRequestAuth] - >() - .mockImplementation(async (_, requestAuth) => ({ - type: 'bearer token', - token: requestAuth.custom as string, - })), - validateCluster: jest.fn().mockReturnValue([]), - }) - .setClusterSupplier({ - getClusters: jest - .fn, []>() - .mockResolvedValue([ - { - name: 'custom-cluster', - url: 'http://my.cluster.url', - authMetadata: { - [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'custom', - }, + + const clusterSupplierMock = { + getClusters: jest.fn().mockImplementation(_ => { + return Promise.resolve([ + { + name: 'custom-cluster', + url: 'http://my.cluster.url', + authMetadata: { + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'custom', }, - ]), - }) - .setFetcher(mockFetcher) - .build(); - app = express().use(router); + }, + ]); + }), + }; + + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', + }, + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, + }), + import('@backstage/plugin-kubernetes-backend/alpha'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testClusterSupplier', + register(env) { + env.registerInit({ + deps: { extension: kubernetesClusterSupplierExtensionPoint }, + async init({ extension }) { + extension.addClusterSupplier(clusterSupplierMock); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testAuthStrategy', + register(env) { + env.registerInit({ + deps: { extension: kubernetesAuthStrategyExtensionPoint }, + async init({ extension }) { + extension.addAuthStrategy('custom', { + getCredential: jest + .fn< + Promise, + [ClusterDetails, KubernetesRequestAuth] + >() + .mockImplementation(async (_, requestAuth) => ({ + type: 'bearer token', + token: requestAuth.custom as string, + })), + validateCluster: jest.fn().mockReturnValue([]), + }); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testFetcher', + register(env) { + env.registerInit({ + deps: { extension: kubernetesFetcherExtensionPoint }, + async init({ extension }) { + extension.addFetcher(mockFetcher); + }, + }); + }, + }), + ], + }); + + app = server; await request(app) - .post('/services/test-service') + .post('/api/kubernetes/services/test-service') .send({ entity: { metadata: { @@ -400,12 +542,8 @@ describe('KubernetesBuilder', () => { }, }; - permissions.authorize.mockReturnValue( - Promise.resolve([{ result: AuthorizeResult.ALLOW }]), - ); - const proxyEndpointRequest = request(app) - .post('/proxy/api/v1/namespaces') + .post('/api/kubernetes/proxy/api/v1/namespaces') .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') .set(HEADER_KUBERNETES_AUTH, 'randomtoken') .send(requestBody); @@ -425,12 +563,8 @@ metadata: name: new-ns `; - permissions.authorize.mockReturnValue( - Promise.resolve([{ result: AuthorizeResult.ALLOW }]), - ); - const proxyEndpointRequest = request(app) - .post('/proxy/api/v1/namespaces') + .post('/api/kubernetes/proxy/api/v1/namespaces') .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') .set(HEADER_KUBERNETES_AUTH, 'randomtoken') .set('content-type', 'application/yaml') @@ -451,12 +585,35 @@ metadata: }, }; - permissions.authorize.mockReturnValue( - Promise.resolve([{ result: AuthorizeResult.DENY }]), - ); + permissionsMock.authorize.mockResolvedValue([ + { result: AuthorizeResult.DENY }, + ]); - const proxyEndpointRequest = request(app) - .post('/proxy/api/v1/namespaces') + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', + }, + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, + }), + permissionsMock.factory, + import('@backstage/plugin-kubernetes-backend/alpha'), + // import('@backstage/plugin-permission-backend/alpha'), + ], + }); + + const proxyEndpointRequest = request(server) + .post('/api/kubernetes/proxy/api/v1/namespaces') .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') .set(HEADER_KUBERNETES_AUTH, 'randomtoken') .send(requestBody); @@ -477,42 +634,90 @@ metadata: return res(ctx.json({ items: [] })); }), ); - permissions.authorize.mockResolvedValue([ - { result: AuthorizeResult.ALLOW }, - ]); - const { router } = await KubernetesBuilder.createBuilder({ - logger: getVoidLogger(), - config, - catalogApi, - permissions, - }) - .addAuthStrategy('custom', { - getCredential: jest - .fn< - Promise, - [ClusterDetails, KubernetesRequestAuth] - >() - .mockResolvedValue({ type: 'anonymous' }), - validateCluster: jest.fn().mockReturnValue([]), - }) - .setClusterSupplier({ - getClusters: jest - .fn, []>() - .mockResolvedValue([ - { - name: 'custom-cluster', - url: 'http://my.cluster.url', - authMetadata: { - [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'custom', - }, + + const clusterSupplierMock = { + getClusters: jest.fn().mockImplementation(_ => { + return Promise.resolve([ + { + name: 'custom-cluster', + url: 'http://my.cluster.url', + authMetadata: { + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'custom', }, - ]), - }) - .build(); - app = express().use(router); + }, + ]); + }), + }; + + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', + }, + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, + }), + import('@backstage/plugin-kubernetes-backend/alpha'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testObjectsProvider', + register(env) { + env.registerInit({ + deps: { extension: kubernetesObjectsProviderExtensionPoint }, + async init({ extension }) { + extension.addObjectsProvider(objectsProviderMock); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testClusterSupplier', + register(env) { + env.registerInit({ + deps: { extension: kubernetesClusterSupplierExtensionPoint }, + async init({ extension }) { + extension.addClusterSupplier(clusterSupplierMock); + }, + }); + }, + }), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testAuthStrategy', + register(env) { + env.registerInit({ + deps: { extension: kubernetesAuthStrategyExtensionPoint }, + async init({ extension }) { + extension.addAuthStrategy('custom', { + getCredential: jest + .fn< + Promise, + [ClusterDetails, KubernetesRequestAuth] + >() + .mockResolvedValue({ type: 'anonymous' }), + validateCluster: jest.fn().mockReturnValue([]), + }); + }, + }); + }, + }), + ], + }); + + app = server; const proxyEndpointRequest = request(app) - .get('/proxy/api/v1/namespaces') + .get('/api/kubernetes/proxy/api/v1/namespaces') .set(HEADER_KUBERNETES_CLUSTER, 'custom-cluster') .set(HEADER_KUBERNETES_AUTH, 'custom-token'); worker.use(rest.all(proxyEndpointRequest.url, req => req.passthrough())); @@ -522,29 +727,44 @@ metadata: }); it('should not permit custom auth strategies with dashes', async () => { - const throwError = () => - KubernetesBuilder.createBuilder({ - logger: getVoidLogger(), - config, - catalogApi, - permissions, - }).addAuthStrategy('custom-strategy', { - getCredential: jest - .fn< - Promise, - [ClusterDetails, KubernetesRequestAuth] - >() - .mockResolvedValue({ type: 'anonymous' }), - validateCluster: jest.fn().mockReturnValue([]), + const throwError = async () => { + await startTestBackend({ + features: [ + import('@backstage/plugin-kubernetes-backend/alpha'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testAuthStrategy', + register(env) { + env.registerInit({ + deps: { extension: kubernetesAuthStrategyExtensionPoint }, + async init({ extension }) { + extension.addAuthStrategy('custom-strategy', { + getCredential: jest + .fn< + Promise, + [ClusterDetails, KubernetesRequestAuth] + >() + .mockResolvedValue({ type: 'anonymous' }), + validateCluster: jest.fn().mockReturnValue([]), + }); + }, + }); + }, + }), + ], }); + }; - expect(throwError).toThrow('Strategy name can not include dashes'); + await expect(throwError).rejects.toThrow( + 'Strategy name can not include dashes', + ); }); }); + describe('get /.well-known/backstage/permissions/metadata', () => { it('lists permissions supported by the kubernetes plugin', async () => { const response = await request(app).get( - '/.well-known/backstage/permissions/metadata', + '/api/kubernetes/.well-known/backstage/permissions/metadata', ); expect(response.status).toEqual(200); diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index fade501417..18d1dc35c9 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -24,28 +24,6 @@ import { ObjectToFetch, } from '@backstage/plugin-kubernetes-node'; -/** - * - * @public - */ -export type KubernetesObjectTypes = - | 'pods' - | 'services' - | 'configmaps' - | 'deployments' - | 'limitranges' - | 'resourcequotas' - | 'replicasets' - | 'horizontalpodautoscalers' - | 'jobs' - | 'cronjobs' - | 'ingresses' - | 'customresources' - | 'statefulsets' - | 'daemonsets'; -// If updating this list, also make sure to update -// `objectTypes` and `apiVersionOverrides` in config.d.ts! - /** * * @public @@ -71,4 +49,5 @@ export interface KubernetesObjectsProviderOptions { */ export type ObjectsByEntityRequest = KubernetesRequestBody; +// TODO remove this re-export as a breaking change after a couple of releases export type * from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-node/api-report.md b/plugins/kubernetes-node/api-report.md index d2981b32d1..2272035742 100644 --- a/plugins/kubernetes-node/api-report.md +++ b/plugins/kubernetes-node/api-report.md @@ -3,19 +3,131 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AuthenticationStrategy as AuthenticationStrategy_2 } from '@backstage/plugin-kubernetes-node'; import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { Entity } from '@backstage/catalog-model'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { FetchResponse } from '@backstage/plugin-kubernetes-common'; +import { JsonObject } from '@backstage/types'; +import { KubernetesClustersSupplier as KubernetesClustersSupplier_2 } from '@backstage/plugin-kubernetes-node'; +import { KubernetesFetcher as KubernetesFetcher_2 } from '@backstage/plugin-kubernetes-node'; +import { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; import { KubernetesObjectsProvider as KubernetesObjectsProvider_2 } from '@backstage/plugin-kubernetes-node'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; +import { KubernetesServiceLocator as KubernetesServiceLocator_2 } from '@backstage/plugin-kubernetes-node'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; +// @public (undocumented) +export interface AuthenticationStrategy { + // (undocumented) + getCredential( + clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, + ): Promise; + // (undocumented) + validateCluster(authMetadata: AuthMetadata): Error[]; +} + +// @public +export type AuthMetadata = Record; + +// @public (undocumented) +export interface ClusterDetails { + // (undocumented) + authMetadata: AuthMetadata; + // (undocumented) + caData?: string | undefined; + // (undocumented) + caFile?: string | undefined; + customResources?: CustomResourceMatcher[]; + dashboardApp?: string; + dashboardParameters?: JsonObject; + dashboardUrl?: string; + name: string; + skipMetricsLookup?: boolean; + // (undocumented) + skipTLSVerify?: boolean; + // (undocumented) + url: string; +} + +// @public (undocumented) +export interface CustomResource extends ObjectToFetch { + // (undocumented) + objectType: 'customresources'; +} + // @public (undocumented) export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { // (undocumented) customResources: CustomResourceMatcher[]; } +// @public (undocumented) +export interface FetchResponseWrapper { + // (undocumented) + errors: KubernetesFetchError[]; + // (undocumented) + responses: FetchResponse[]; +} + +// @public +export interface KubernetesAuthStrategyExtensionPoint { + // (undocumented) + addAuthStrategy(key: string, strategy: AuthenticationStrategy_2): void; +} + +// @public +export const kubernetesAuthStrategyExtensionPoint: ExtensionPoint; + +// @public +export interface KubernetesClustersSupplier { + getClusters(): Promise; +} + +// @public +export interface KubernetesClusterSupplierExtensionPoint { + // (undocumented) + addClusterSupplier(clusterSupplier: KubernetesClustersSupplier_2): void; +} + +// @public +export const kubernetesClusterSupplierExtensionPoint: ExtensionPoint; + +// @public +export type KubernetesCredential = + | { + type: 'bearer token'; + token: string; + } + | { + type: 'anonymous'; + }; + +// @public +export interface KubernetesFetcher { + // (undocumented) + fetchObjectsForService( + params: ObjectFetchParams, + ): Promise; + // (undocumented) + fetchPodMetricsByNamespaces( + clusterDetails: ClusterDetails, + credential: KubernetesCredential, + namespaces: Set, + labelSelector?: string, + ): Promise; +} + +// @public +export interface KubernetesFetcherExtensionPoint { + // (undocumented) + addFetcher(fetcher: KubernetesFetcher_2): void; +} + +// @public +export const kubernetesFetcherExtensionPoint: ExtensionPoint; + // @public (undocumented) export interface KubernetesObjectsByEntity { // (undocumented) @@ -44,4 +156,79 @@ export interface KubernetesObjectsProviderExtensionPoint { // @public export const kubernetesObjectsProviderExtensionPoint: ExtensionPoint; + +// @public (undocumented) +export type KubernetesObjectTypes = + | 'pods' + | 'services' + | 'configmaps' + | 'deployments' + | 'limitranges' + | 'resourcequotas' + | 'replicasets' + | 'horizontalpodautoscalers' + | 'jobs' + | 'cronjobs' + | 'ingresses' + | 'customresources' + | 'statefulsets' + | 'daemonsets'; + +// @public +export interface KubernetesServiceLocator { + // (undocumented) + getClustersByEntity( + entity: Entity, + requestContext: ServiceLocatorRequestContext, + ): Promise<{ + clusters: ClusterDetails[]; + }>; +} + +// @public +export interface KubernetesServiceLocatorExtensionPoint { + // (undocumented) + addServiceLocator(serviceLocator: KubernetesServiceLocator_2): void; +} + +// @public +export const kubernetesServiceLocatorExtensionPoint: ExtensionPoint; + +// @public (undocumented) +export interface ObjectFetchParams { + // (undocumented) + clusterDetails: ClusterDetails; + // (undocumented) + credential: KubernetesCredential; + // (undocumented) + customResources: CustomResource[]; + // (undocumented) + labelSelector?: string; + // (undocumented) + namespace?: string; + // (undocumented) + objectTypesToFetch: Set; + // (undocumented) + serviceId: string; +} + +// @public (undocumented) +export interface ObjectToFetch { + // (undocumented) + apiVersion: string; + // (undocumented) + group: string; + // (undocumented) + objectType: KubernetesObjectTypes; + // (undocumented) + plural: string; +} + +// @public (undocumented) +export interface ServiceLocatorRequestContext { + // (undocumented) + customResources: CustomResourceMatcher[]; + // (undocumented) + objectTypesToFetch: Set; +} ``` diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 37922fc2e9..56f4ba01c4 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -30,7 +30,6 @@ "dependencies": { "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", - "@backstage/plugin-kubernetes-backend": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/types": "workspace:^" } diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index 59582bc0f2..a0f48d0c26 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -14,7 +14,6 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; -import { KubernetesObjectTypes } from '@backstage/plugin-kubernetes-backend'; import { CustomResourceMatcher, FetchResponse, @@ -154,6 +153,28 @@ export interface AuthenticationStrategy { validateCluster(authMetadata: AuthMetadata): Error[]; } +/** + * + * @public + */ +export type KubernetesObjectTypes = + | 'pods' + | 'services' + | 'configmaps' + | 'deployments' + | 'limitranges' + | 'resourcequotas' + | 'replicasets' + | 'horizontalpodautoscalers' + | 'jobs' + | 'cronjobs' + | 'ingresses' + | 'customresources' + | 'statefulsets' + | 'daemonsets'; +// If updating this list, also make sure to update +// `objectTypes` and `apiVersionOverrides` in config.d.ts on @backstage/plugin-kubernetes-backend! + /** * * @public diff --git a/yarn.lock b/yarn.lock index 71aa0872c4..4db4eb15e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7674,7 +7674,6 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" - "@backstage/plugin-kubernetes-backend": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" "@backstage/types": "workspace:^" languageName: unknown From 19248768c5ecc2e2dd393fa0c5d4f7d9ffcdad5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mauricio=20G=C3=B3mez=20P?= Date: Mon, 27 Nov 2023 15:35:15 -0500 Subject: [PATCH 6/7] Update .changeset/plenty-falcons-travel.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jamie Klassen Signed-off-by: Andrés Mauricio Gómez P --- .changeset/plenty-falcons-travel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/plenty-falcons-travel.md b/.changeset/plenty-falcons-travel.md index 0c8706cde0..9e1f08246d 100644 --- a/.changeset/plenty-falcons-travel.md +++ b/.changeset/plenty-falcons-travel.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-kubernetes-node': minor +'@backstage/plugin-kubernetes-node': patch '@backstage/plugin-kubernetes-backend': patch --- From 472a47f1635204d892532bf528626d70bfd720c9 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Tue, 12 Dec 2023 11:37:36 -0500 Subject: [PATCH 7/7] Adding a deprecation message for the types Signed-off-by: Andres Mauricio Gomez P --- plugins/kubernetes-backend/api-report.md | 120 +++++++++++------- plugins/kubernetes-backend/src/auth/types.ts | 16 ++- plugins/kubernetes-backend/src/types/index.ts | 9 -- plugins/kubernetes-backend/src/types/types.ts | 84 ++++++++++-- 4 files changed, 156 insertions(+), 73 deletions(-) diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 04c7cf8b1e..e6996484dd 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -3,25 +3,20 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; -import { AuthMetadata } from '@backstage/plugin-kubernetes-node'; +import { AuthenticationStrategy as AuthenticationStrategy_2 } from '@backstage/plugin-kubernetes-node'; import { CatalogApi } from '@backstage/catalog-client'; -import { ClusterDetails } from '@backstage/plugin-kubernetes-node'; +import { ClusterDetails as ClusterDetails_2 } from '@backstage/plugin-kubernetes-node'; import { Config } from '@backstage/config'; -import { CustomResource } from '@backstage/plugin-kubernetes-node'; -import { CustomResourcesByEntity } from '@backstage/plugin-kubernetes-node'; +import { CustomResource as CustomResource_2 } from '@backstage/plugin-kubernetes-node'; import { Duration } from 'luxon'; import express from 'express'; -import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; -import { KubernetesCredential } from '@backstage/plugin-kubernetes-node'; -import { KubernetesFetcher } from '@backstage/plugin-kubernetes-node'; -import { KubernetesObjectsByEntity } from '@backstage/plugin-kubernetes-node'; -import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; +import * as k8sAuthTypes from '@backstage/plugin-kubernetes-node'; +import { KubernetesClustersSupplier as KubernetesClustersSupplier_2 } from '@backstage/plugin-kubernetes-node'; +import { KubernetesObjectsProvider as KubernetesObjectsProvider_2 } from '@backstage/plugin-kubernetes-node'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; -import { KubernetesServiceLocator } from '@backstage/plugin-kubernetes-node'; import { Logger } from 'winston'; -import { ObjectToFetch } from '@backstage/plugin-kubernetes-node'; +import { ObjectToFetch as ObjectToFetch_2 } from '@backstage/plugin-kubernetes-node'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RequestHandler } from 'http-proxy-middleware'; @@ -46,9 +41,11 @@ export class AnonymousStrategy implements AuthenticationStrategy { validateCluster(): Error[]; } -export { AuthenticationStrategy }; +// @public @deprecated (undocumented) +export type AuthenticationStrategy = k8sAuthTypes.AuthenticationStrategy; -export { AuthMetadata }; +// @public @deprecated (undocumented) +export type AuthMetadata = k8sAuthTypes.AuthMetadata; // @public (undocumented) export class AwsIamStrategy implements AuthenticationStrategy { @@ -68,12 +65,17 @@ export class AzureIdentityStrategy implements AuthenticationStrategy { validateCluster(): Error[]; } -export { ClusterDetails }; +// @public @deprecated (undocumented) +export type ClusterDetails = k8sAuthTypes.ClusterDetails; // @public @deprecated export function createRouter(options: RouterOptions): Promise; -export { CustomResourcesByEntity }; +// @public @deprecated (undocumented) +export type CustomResource = k8sAuthTypes.CustomResource; + +// @public @deprecated (undocumented) +export type CustomResourcesByEntity = k8sAuthTypes.CustomResourcesByEntity; // @public (undocumented) export const DEFAULT_OBJECTS: ObjectToFetch[]; @@ -97,6 +99,9 @@ export type DispatchStrategyOptions = { }; }; +// @public @deprecated (undocumented) +export type FetchResponseWrapper = k8sAuthTypes.FetchResponseWrapper; + // @public (undocumented) export class GoogleServiceAccountStrategy implements AuthenticationStrategy { // (undocumented) @@ -131,37 +136,37 @@ export class KubernetesBuilder { build(): KubernetesBuilderReturn; // (undocumented) protected buildAuthStrategyMap(): { - [key: string]: AuthenticationStrategy; + [key: string]: AuthenticationStrategy_2; }; // (undocumented) protected buildClusterSupplier( refreshInterval: Duration, - ): KubernetesClustersSupplier; + ): KubernetesClustersSupplier_2; // (undocumented) - protected buildCustomResources(): CustomResource[]; + protected buildCustomResources(): CustomResource_2[]; // (undocumented) protected buildFetcher(): KubernetesFetcher; // (undocumented) protected buildHttpServiceLocator( - _clusterSupplier: KubernetesClustersSupplier, + _clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesServiceLocator; // (undocumented) protected buildMultiTenantServiceLocator( - clusterSupplier: KubernetesClustersSupplier, + clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesServiceLocator; // (undocumented) protected buildObjectsProvider( options: KubernetesObjectsProviderOptions, - ): KubernetesObjectsProvider; + ): KubernetesObjectsProvider_2; // (undocumented) protected buildProxy( logger: Logger, - clusterSupplier: KubernetesClustersSupplier, + clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesProxy; // (undocumented) protected buildRouter( - objectsProvider: KubernetesObjectsProvider, - clusterSupplier: KubernetesClustersSupplier, + objectsProvider: KubernetesObjectsProvider_2, + clusterSupplier: KubernetesClustersSupplier_2, catalogApi: CatalogApi, proxy: KubernetesProxy, permissionApi: PermissionEvaluator, @@ -169,11 +174,11 @@ export class KubernetesBuilder { // (undocumented) protected buildServiceLocator( method: ServiceLocatorMethod, - clusterSupplier: KubernetesClustersSupplier, + clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesServiceLocator; // (undocumented) protected buildSingleTenantServiceLocator( - clusterSupplier: KubernetesClustersSupplier, + clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesServiceLocator; // (undocumented) static createBuilder(env: KubernetesEnvironment): KubernetesBuilder; @@ -181,26 +186,26 @@ export class KubernetesBuilder { protected readonly env: KubernetesEnvironment; // (undocumented) protected fetchClusterDetails( - clusterSupplier: KubernetesClustersSupplier, - ): Promise; + clusterSupplier: KubernetesClustersSupplier_2, + ): Promise; // (undocumented) protected getAuthStrategyMap(): { - [key: string]: AuthenticationStrategy; + [key: string]: AuthenticationStrategy_2; }; // (undocumented) - protected getClusterSupplier(): KubernetesClustersSupplier; + protected getClusterSupplier(): KubernetesClustersSupplier_2; // (undocumented) protected getFetcher(): KubernetesFetcher; // (undocumented) protected getObjectsProvider( options: KubernetesObjectsProviderOptions, - ): KubernetesObjectsProvider; + ): KubernetesObjectsProvider_2; // (undocumented) - protected getObjectTypesToFetch(): ObjectToFetch[] | undefined; + protected getObjectTypesToFetch(): ObjectToFetch_2[] | undefined; // (undocumented) protected getProxy( logger: Logger, - clusterSupplier: KubernetesClustersSupplier, + clusterSupplier: KubernetesClustersSupplier_2, ): KubernetesProxy; // (undocumented) protected getServiceLocator(): KubernetesServiceLocator; @@ -211,13 +216,13 @@ export class KubernetesBuilder { [key: string]: AuthenticationStrategy; }): void; // (undocumented) - setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier): this; + setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier_2): this; // (undocumented) setDefaultClusterRefreshInterval(refreshInterval: Duration): this; // (undocumented) setFetcher(fetcher?: KubernetesFetcher): this; // (undocumented) - setObjectsProvider(objectsProvider?: KubernetesObjectsProvider): this; + setObjectsProvider(objectsProvider?: KubernetesObjectsProvider_2): this; // (undocumented) setProxy(proxy?: KubernetesProxy): this; // (undocumented) @@ -227,20 +232,23 @@ export class KubernetesBuilder { // @public export type KubernetesBuilderReturn = Promise<{ router: express.Router; - clusterSupplier: KubernetesClustersSupplier; + clusterSupplier: KubernetesClustersSupplier_2; customResources: CustomResource[]; fetcher: KubernetesFetcher; proxy: KubernetesProxy; - objectsProvider: KubernetesObjectsProvider; + objectsProvider: KubernetesObjectsProvider_2; serviceLocator: KubernetesServiceLocator; authStrategyMap: { [key: string]: AuthenticationStrategy; }; }>; -export { KubernetesClustersSupplier }; +// @public @deprecated (undocumented) +export type KubernetesClustersSupplier = + k8sAuthTypes.KubernetesClustersSupplier; -export { KubernetesCredential }; +// @public @deprecated (undocumented) +export type KubernetesCredential = k8sAuthTypes.KubernetesCredential; // @public (undocumented) export interface KubernetesEnvironment { @@ -254,26 +262,31 @@ export interface KubernetesEnvironment { permissions: PermissionEvaluator; } -export { KubernetesObjectsByEntity }; +// @public @deprecated (undocumented) +export type KubernetesFetcher = k8sAuthTypes.KubernetesFetcher; -export { KubernetesObjectsProvider }; +// @public @deprecated (undocumented) +export type KubernetesObjectsProvider = k8sAuthTypes.KubernetesObjectsProvider; // @public (undocumented) export interface KubernetesObjectsProviderOptions { // (undocumented) config: Config; // (undocumented) - customResources: CustomResource[]; + customResources: k8sAuthTypes.CustomResource[]; // (undocumented) - fetcher: KubernetesFetcher; + fetcher: k8sAuthTypes.KubernetesFetcher; // (undocumented) logger: Logger; // (undocumented) - objectTypesToFetch?: ObjectToFetch[]; + objectTypesToFetch?: k8sAuthTypes.ObjectToFetch[]; // (undocumented) - serviceLocator: KubernetesServiceLocator; + serviceLocator: k8sAuthTypes.KubernetesServiceLocator; } +// @public @deprecated (undocumented) +export type KubernetesObjectTypes = k8sAuthTypes.KubernetesObjectTypes; + // @public export class KubernetesProxy { constructor(options: KubernetesProxyOptions); @@ -295,9 +308,18 @@ export type KubernetesProxyOptions = { authStrategy: AuthenticationStrategy; }; +// @public @deprecated (undocumented) +export type KubernetesServiceLocator = k8sAuthTypes.KubernetesServiceLocator; + +// @public @deprecated (undocumented) +export type ObjectFetchParams = k8sAuthTypes.ObjectFetchParams; + // @public (undocumented) export type ObjectsByEntityRequest = KubernetesRequestBody; +// @public @deprecated (undocumented) +export type ObjectToFetch = k8sAuthTypes.ObjectToFetch; + // @public (undocumented) export class OidcStrategy implements AuthenticationStrategy { // (undocumented) @@ -336,12 +358,14 @@ export class ServiceAccountStrategy implements AuthenticationStrategy { // @public (undocumented) export type ServiceLocatorMethod = 'multiTenant' | 'singleTenant' | 'http'; +// @public @deprecated (undocumented) +export type ServiceLocatorRequestContext = + k8sAuthTypes.ServiceLocatorRequestContext; + // @public (undocumented) export type SigningCreds = { accessKeyId: string | undefined; secretAccessKey: string | undefined; sessionToken: string | undefined; }; - -export * from '@backstage/plugin-kubernetes-node'; ``` diff --git a/plugins/kubernetes-backend/src/auth/types.ts b/plugins/kubernetes-backend/src/auth/types.ts index c7d60e8f2b..9b33265448 100644 --- a/plugins/kubernetes-backend/src/auth/types.ts +++ b/plugins/kubernetes-backend/src/auth/types.ts @@ -14,9 +14,15 @@ * limitations under the License. */ -// TODO remove this re-export as a breaking change after a couple of releases +import * as k8sAuthTypes from '@backstage/plugin-kubernetes-node'; -export type { - AuthenticationStrategy, - KubernetesCredential, -} from '@backstage/plugin-kubernetes-node'; +// TODO remove this re-export as a breaking change after a couple of releases +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type AuthenticationStrategy = k8sAuthTypes.AuthenticationStrategy; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesCredential = k8sAuthTypes.KubernetesCredential; diff --git a/plugins/kubernetes-backend/src/types/index.ts b/plugins/kubernetes-backend/src/types/index.ts index 17ce00d020..db229eae34 100644 --- a/plugins/kubernetes-backend/src/types/index.ts +++ b/plugins/kubernetes-backend/src/types/index.ts @@ -15,12 +15,3 @@ */ export * from './types'; - -export type { - AuthMetadata, - ClusterDetails, - CustomResourcesByEntity, - KubernetesClustersSupplier, - KubernetesObjectsByEntity, - KubernetesObjectsProvider, -} from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 18d1dc35c9..57a12bb58a 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -17,12 +17,7 @@ import { Logger } from 'winston'; import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; -import { - CustomResource, - KubernetesFetcher, - KubernetesServiceLocator, - ObjectToFetch, -} from '@backstage/plugin-kubernetes-node'; +import * as k8sTypes from '@backstage/plugin-kubernetes-node'; /** * @@ -37,10 +32,10 @@ export type ServiceLocatorMethod = 'multiTenant' | 'singleTenant' | 'http'; // T export interface KubernetesObjectsProviderOptions { logger: Logger; config: Config; - fetcher: KubernetesFetcher; - serviceLocator: KubernetesServiceLocator; - customResources: CustomResource[]; - objectTypesToFetch?: ObjectToFetch[]; + fetcher: k8sTypes.KubernetesFetcher; + serviceLocator: k8sTypes.KubernetesServiceLocator; + customResources: k8sTypes.CustomResource[]; + objectTypesToFetch?: k8sTypes.ObjectToFetch[]; } /** @@ -50,4 +45,71 @@ export interface KubernetesObjectsProviderOptions { export type ObjectsByEntityRequest = KubernetesRequestBody; // TODO remove this re-export as a breaking change after a couple of releases -export type * from '@backstage/plugin-kubernetes-node'; +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesObjectsProvider = k8sTypes.KubernetesObjectsProvider; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type CustomResourcesByEntity = k8sTypes.CustomResourcesByEntity; + +/** + * @public + * @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type AuthMetadata = k8sTypes.AuthMetadata; + +/** + * @public + * @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type ClusterDetails = k8sTypes.ClusterDetails; + +/** + * @public + * @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesClustersSupplier = k8sTypes.KubernetesClustersSupplier; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesObjectTypes = k8sTypes.KubernetesObjectTypes; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type ObjectToFetch = k8sTypes.ObjectToFetch; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type CustomResource = k8sTypes.CustomResource; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type ObjectFetchParams = k8sTypes.ObjectFetchParams; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type FetchResponseWrapper = k8sTypes.FetchResponseWrapper; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesFetcher = k8sTypes.KubernetesFetcher; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type ServiceLocatorRequestContext = + k8sTypes.ServiceLocatorRequestContext; + +/** + * @public @deprecated Import it from \@backstage/plugin-kubernetes-node instead + */ +export type KubernetesServiceLocator = k8sTypes.KubernetesServiceLocator;