Skip to content

Commit

Permalink
test: Add tests for config.ts and parser.ts (#186)
Browse files Browse the repository at this point in the history
* feat: Add resource parser

Signed-off-by: SamoKopecky <[email protected]>

* test: Add tests for config.ts and parser.ts

Signed-off-by: SamoKopecky <[email protected]>

Signed-off-by: SamoKopecky <[email protected]>
  • Loading branch information
SamoKopecky authored Nov 22, 2022
1 parent 9ce9fde commit 35c4ff6
Show file tree
Hide file tree
Showing 9 changed files with 626 additions and 24 deletions.
3 changes: 2 additions & 1 deletion plugins/rhacm-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"@backstage/catalog-client": "^1.1.2",
"@backstage/catalog-model": "^1.1.3",
"@backstage/config": "^1.0.4",
"@internal/backstage-plugin-rhacm-common": "*",
"@backstage/plugin-catalog-node": "^1.2.1",
"@internal/backstage-plugin-rhacm-common": "*",
"@kubernetes/client-node": "^0.17.1",
"@types/express": "*",
"express": "^4.17.1",
Expand All @@ -42,6 +42,7 @@
"@backstage/cli": "^0.21.1",
"@types/supertest": "^2.0.8",
"msw": "^0.35.0",
"nock": "^13.2.9",
"supertest": "^4.0.2"
},
"files": [
Expand Down
110 changes: 110 additions & 0 deletions plugins/rhacm-backend/src/helpers/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { ConfigReader } from '@backstage/config';
import { getHubClusterFromConfig } from './config';

const createConfig = (clusters: any[]) => ({
kubernetes: {
clusterLocatorMethods: [
{
type: 'config',
clusters: clusters,
},
],
},
rhacm: {
hub: 'cluster2',
},
});

const createConfigParseResult = (name: string) => ({
data: { name: name },
context: 'mock-config',
prefix: 'kubernetes.clusterLocatorMethods[0].clusters[1]',
fallback: undefined,
filteredKeys: undefined,
notifiedFilteredKeys: new Set(),
});

describe('getHubClusterFromConfig', () => {
it('should get the correct hub cluster from multiple configured clusters', () => {
const config = new ConfigReader(
createConfig([
{
name: 'cluster1',
},
{
name: 'cluster2',
},
{
name: 'cluster3',
},
]),
);

const result = getHubClusterFromConfig(config);

expect(result).toEqual(createConfigParseResult('cluster2'));
});

it('should throw an error when the hub cluster is not found', () => {
const config = new ConfigReader(
createConfig([
{
name: 'cluster4',
},
]),
);

const result = () => getHubClusterFromConfig(config);

expect(result).toThrow('Hub cluster not defined in kubernetes config');
});

it('should throw an error when there are no cluster configured', () => {
const config = new ConfigReader(createConfig([]));

const result = () => {
getHubClusterFromConfig(config);
};

expect(result).toThrow('Hub cluster not defined in kubernetes config');
});

it('should throw an error when locator methods are empty', () => {
const config = new ConfigReader({
kubernetes: {
clusterLocatorMethods: [],
},
rhacm: {
hub: 'cluster2',
},
});

const result = () => getHubClusterFromConfig(config);

expect(result).toThrow('Hub cluster not defined in kubernetes config');
});

it('should throw an error when there is to hub cluster configured', () => {
const config = new ConfigReader({});

const result = () => getHubClusterFromConfig(config);

expect(result).toThrow(
"Hub cluster must be specified in config at 'rhacm.hub'",
);
});
});

describe('getHubClusterName', () => {
it('should get the hub cluster name from config', () => {
const config = new ConfigReader({
rhacm: {
hub: 'cluster2',
},
});

const result = config.getString('rhacm.hub');

expect(result).toBe('cluster2');
});
});
8 changes: 4 additions & 4 deletions plugins/rhacm-backend/src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { Config } from '@backstage/config';
const CLUSTERS_PATH = 'kubernetes.clusterLocatorMethods';
const HUB_CLUSTER_CONFIG_PATH = 'rhacm.hub';

export const getHubClusterName = (config: Config) =>
config.getString(HUB_CLUSTER_CONFIG_PATH);

export const getHubClusterFromConfig = (config: Config) => {
try {
config.getString(HUB_CLUSTER_CONFIG_PATH);
getHubClusterName(config);
} catch (err) {
throw new Error(
`Hub cluster must be specified in config at '${HUB_CLUSTER_CONFIG_PATH}'`,
Expand All @@ -24,6 +27,3 @@ export const getHubClusterFromConfig = (config: Config) => {
}
return hub;
};

export const getHubClusterName = (config: Config) =>
config.getString(HUB_CLUSTER_CONFIG_PATH);
178 changes: 178 additions & 0 deletions plugins/rhacm-backend/src/helpers/kubernetes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { ConfigReader } from '@backstage/config';
import {
getCustomObjectsApi,
hubApiClient,
getManagedCluster,
getManagedClusters,
} from './kubernetes';
import { createLogger } from 'winston';
import transports from 'winston/lib/winston/transports';
import { CustomObjectsApi, KubeConfig } from '@kubernetes/client-node';
import nock from 'nock';

const logger = createLogger({
transports: [new transports.Console({ silent: true })],
});

describe('getCustomObjectsApi', () => {
it('should use the default config if there is no service account token configured', () => {
process.env.KUBECONFIG = `${__dirname}/test_data/kubeconfig.yaml`;
const clusterConfig = new ConfigReader({
name: 'cluster1',
});

const result = getCustomObjectsApi(clusterConfig, logger);

expect(result.basePath).toBe('http://example.com');
// These fields aren't on the type but are there
const auth = (result as any).authentications.default;
expect(auth.clusters[0].name).toBe('default-cluster');
expect(auth.users[0].token).toBeUndefined();
});

it('should use the provided config in the returned api client', () => {
const clusterConfig = new ConfigReader({
name: 'cluster1',
serviceAccountToken: 'TOKEN',
url: 'http://cluster.com',
});

const result = getCustomObjectsApi(clusterConfig, logger);

expect(result.basePath).toBe('http://cluster.com');
// These fields aren't on the type but are there
const auth = (result as any).authentications.default;
expect(auth.clusters[0].name).toBe('cluster1');
expect(auth.users[0].token).toBe('TOKEN');
});
});

describe('hubApiClient', () => {
it('should return an api client configured with the hub cluster', () => {
const config = new ConfigReader({
kubernetes: {
clusterLocatorMethods: [
{
type: 'config',
clusters: [
{
name: 'cluster2',
serviceAccountToken: 'TOKEN',
url: 'http://cluster2.com',
},
],
},
],
},
rhacm: {
hub: 'cluster2',
},
});

const result = hubApiClient(config, logger);

expect(result.basePath).toBe('http://cluster2.com');
// These fields aren't on the type but are there
const auth = (result as any).authentications.default;
expect(auth.clusters[0].name).toBe('cluster2');
});
});

const kubeConfig = {
clusters: [{ name: 'cluster', server: 'https://127.0.0.1:51010' }],
users: [{ name: 'user', password: 'password' }],
contexts: [{ name: 'currentContext', cluster: 'cluster', user: 'user' }],
currentContext: 'currentContext',
};

const getApi = () => {
const kc = new KubeConfig();
kc.loadFromOptions(kubeConfig);
return kc.makeApiClient(CustomObjectsApi);
};

describe('getManagedClusters', () => {
it('should return some clusters', async () => {
nock(kubeConfig.clusters[0].server)
.get('/apis/cluster.open-cluster-management.io/v1/managedclusters')
.reply(200, {
body: {
items: [
{
kind: 'ManagedCluster',
metadata: {
name: 'cluster1',
},
},
{
kind: 'ManagedCluster',
metadata: {
name: 'cluster2',
},
},
],
},
});

const result: any = await getManagedClusters(getApi());
expect(result.body.items[0].metadata.name).toBe('cluster1');
expect(result.body.items[1].metadata.name).toBe('cluster2');
});
});

describe('getManagedCluster', () => {
it('should return the correct cluster', async () => {
nock(kubeConfig.clusters[0].server)
.get(
'/apis/cluster.open-cluster-management.io/v1/managedclusters/cluster1',
)
.reply(200, {
body: {
metadata: {
name: 'cluster1',
},
},
});
nock(kubeConfig.clusters[0].server)
.get(
'/apis/cluster.open-cluster-management.io/v1/managedclusters/cluster2',
)
.reply(200, {
body: {
metadata: {
name: 'cluster2',
},
},
});

const result: any = await getManagedCluster(getApi(), 'cluster1');

expect(result.body.metadata.name).toBe('cluster1');
});

it('should return an error object when cluster is not found', async () => {
const errorResponse = {
kind: 'Status',
apiVersion: 'v1',
metadata: {},
status: 'Failure',
message:
'managedclusters.cluster.open-cluster-management.io "wrong_cluster" not found',
reason: 'NotFound',
code: 404,
};

nock(kubeConfig.clusters[0].server)
.get(
'/apis/cluster.open-cluster-management.io/v1/managedclusters/wrong_cluster',
)
.reply(404, errorResponse);

const result = await getManagedCluster(getApi(), 'wrong_cluster').catch(
r => r,
);

expect(result.statusCode).toBe(404);
expect(result.name).toBe('NotFound');
});
});
Loading

0 comments on commit 35c4ff6

Please sign in to comment.