feat: add test and basic docs for catalog cluster locator
Signed-off-by: Jonah Back <jonah@jonahback.com>
This commit is contained in:
@@ -57,12 +57,17 @@ This is an array used to determine where to retrieve cluster configuration from.
|
||||
|
||||
Valid cluster locator methods are:
|
||||
|
||||
- [`catalog`](#catalog)
|
||||
- [`config`](#config)
|
||||
- [`gke`](#gke)
|
||||
- [custom `KubernetesClustersSupplier`](#custom-kubernetesclusterssupplier)
|
||||
|
||||
#### `config`
|
||||
|
||||
This cluster locator method will read cluster information from the catalog.
|
||||
|
||||
#### `config`
|
||||
|
||||
This cluster locator method will read cluster information from your app-config
|
||||
(see below).
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export default async function createPlugin(
|
||||
const { router } = await KubernetesBuilder.createBuilder({
|
||||
logger: env.logger,
|
||||
config: env.config,
|
||||
discovery: env.discovery,
|
||||
}).build();
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 '@backstage/backend-common';
|
||||
import { CatalogClusterLocator } from './CatalogClusterLocator';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
|
||||
describe('CatalogClusterLocator', () => {
|
||||
it('empty clusters returns empty cluster details', async () => {
|
||||
const mockCatalogApi = {
|
||||
getEntityByRef: jest.fn(),
|
||||
getEntities: async () => ({
|
||||
items: [
|
||||
{
|
||||
apiVersion: 'version',
|
||||
kind: 'User',
|
||||
metadata: {
|
||||
annotations: {
|
||||
'kubernetes.io/api-server': 'https://apiserver.com',
|
||||
'kubernetes.io/api-server-certificate-authority': 'caData',
|
||||
'kubernetes.io/auth-provider': 'aws',
|
||||
},
|
||||
name: 'owned',
|
||||
namespace: 'default',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
} as Partial<CatalogApi> as CatalogApi;
|
||||
|
||||
const sut = CatalogClusterLocator.fromConfig(mockCatalogApi);
|
||||
|
||||
const result = await sut.getClusters();
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toMatchObject({
|
||||
name: 'owned',
|
||||
url: 'https://apiserver.com',
|
||||
caData: 'caData',
|
||||
authProvider: 'aws',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
* Copyright 2022 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.
|
||||
@@ -15,21 +15,17 @@
|
||||
*/
|
||||
|
||||
import { ClusterDetails, KubernetesClustersSupplier } from '../types/types';
|
||||
import {
|
||||
CATALOG_FILTER_EXISTS,
|
||||
CatalogClient,
|
||||
} from '@backstage/catalog-client';
|
||||
import { DiscoveryApi } from '@backstage/core-plugin-api';
|
||||
import { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';
|
||||
|
||||
export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
private catalogClient: CatalogClient;
|
||||
private catalogClient: CatalogApi;
|
||||
|
||||
constructor(catalogClient: CatalogClient) {
|
||||
constructor(catalogClient: CatalogApi) {
|
||||
this.catalogClient = catalogClient;
|
||||
}
|
||||
|
||||
static fromConfig(discoveryApi: DiscoveryApi): CatalogClusterLocator {
|
||||
return new CatalogClusterLocator(new CatalogClient({ discoveryApi }));
|
||||
static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {
|
||||
return new CatalogClusterLocator(catalogApi);
|
||||
}
|
||||
|
||||
async getClusters(): Promise<ClusterDetails[]> {
|
||||
@@ -55,13 +51,13 @@ export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
name: entity.metadata.name,
|
||||
// @ts-ignore filtered out by catalog-client query.
|
||||
url: entity.metadata.annotations['kubernetes.io/api-server'],
|
||||
// @ts-ignore filtered out by catalog-client query.
|
||||
caData:
|
||||
// @ts-ignore filtered out by catalog-client query.
|
||||
entity.metadata.annotations[
|
||||
'kubernetes.io/api-server-certificate-authority'
|
||||
],
|
||||
// @ts-ignore filtered out by catalog-client query.
|
||||
authProvider:
|
||||
// @ts-ignore filtered out by catalog-client query.
|
||||
entity.metadata.annotations['kubernetes.io/auth-provider'],
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ import { Duration } from 'luxon';
|
||||
import { ClusterDetails, KubernetesClustersSupplier } from '../types/types';
|
||||
import { ConfigClusterLocator } from './ConfigClusterLocator';
|
||||
import { GkeClusterLocator } from './GkeClusterLocator';
|
||||
import { CatalogClusterLocator } from './CatalogClusterLocator';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common/dist';
|
||||
import { CatalogClient } from '@backstage/catalog-client';
|
||||
|
||||
class CombinedClustersSupplier implements KubernetesClustersSupplier {
|
||||
constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}
|
||||
@@ -38,13 +41,17 @@ class CombinedClustersSupplier implements KubernetesClustersSupplier {
|
||||
|
||||
export const getCombinedClusterSupplier = (
|
||||
rootConfig: Config,
|
||||
discovery: PluginEndpointDiscovery,
|
||||
refreshInterval: Duration | undefined = undefined,
|
||||
): KubernetesClustersSupplier => {
|
||||
const catalogClient = new CatalogClient({ discoveryApi: discovery });
|
||||
const clusterSuppliers = rootConfig
|
||||
.getConfigArray('kubernetes.clusterLocatorMethods')
|
||||
.map(clusterLocatorMethod => {
|
||||
const type = clusterLocatorMethod.getString('type');
|
||||
switch (type) {
|
||||
case 'catalog':
|
||||
return CatalogClusterLocator.fromConfig(catalogClient);
|
||||
case 'config':
|
||||
return ConfigClusterLocator.fromConfig(clusterLocatorMethod);
|
||||
case 'gke':
|
||||
|
||||
@@ -37,10 +37,12 @@ import {
|
||||
KubernetesFanOutHandler,
|
||||
} from './KubernetesFanOutHandler';
|
||||
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common/dist';
|
||||
|
||||
export interface KubernetesEnvironment {
|
||||
logger: Logger;
|
||||
config: Config;
|
||||
discovery: PluginEndpointDiscovery;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +173,11 @@ export class KubernetesBuilder {
|
||||
refreshInterval: Duration,
|
||||
): KubernetesClustersSupplier {
|
||||
const config = this.env.config;
|
||||
return getCombinedClusterSupplier(config, refreshInterval);
|
||||
return getCombinedClusterSupplier(
|
||||
config,
|
||||
this.env.discovery,
|
||||
refreshInterval,
|
||||
);
|
||||
}
|
||||
|
||||
protected buildObjectsProvider(
|
||||
|
||||
Reference in New Issue
Block a user