feat: add test and basic docs for catalog cluster locator

Signed-off-by: Jonah Back <jonah@jonahback.com>
This commit is contained in:
Jonah Back
2022-06-20 13:11:36 -07:00
parent 22c1fc0f6d
commit cb86da6467
6 changed files with 84 additions and 13 deletions
@@ -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(