Skip to content

Commit

Permalink
fix(kiali): remove IstioConfig extra, Fix links and add kiali control (
Browse files Browse the repository at this point in the history
…janus-idp#1452)

* fix(kiali): remove IstioConfig extra, Fix links and add kiali control

* Fix links in details views

* Add initial tests

---------

Co-authored-by: Alberto Gutierrez <aljesusg>
  • Loading branch information
aljesusg authored May 2, 2024
1 parent 09f27b7 commit 51a35f0
Show file tree
Hide file tree
Showing 36 changed files with 831 additions and 484 deletions.
4 changes: 2 additions & 2 deletions plugins/kiali-backend/__fixtures__/data/config/status.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"status": {
"Kiali commit hash": "72a2496cb4ed1545457a68e34fe3e81409b1611d",
"Kiali container version": "v1.71.0-SNAPSHOT",
"Kiali container version": "v1.73.0-SNAPSHOT",
"Kiali state": "running",
"Kiali version": "v1.71.0-SNAPSHOT",
"Kiali version": "v1.73.0-SNAPSHOT",
"Mesh name": "Istio",
"Mesh version": "1.17.1"
},
Expand Down
34 changes: 34 additions & 0 deletions plugins/kiali-backend/src/clients/KialiAPIConnector.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createLogger, transports } from 'winston';

import supported from '../kiali_supported.json';
import { KIALI_CORE_VERSION, KialiApiImpl } from './KialiAPIConnector';

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

const kialiApi = new KialiApiImpl({
logger: logger,
kiali: { url: 'https://localhost:4000' },
});

describe('kiali Api Connector', () => {
describe('Validate suported version', () => {
it('Plugin support the version', () => {
const versionsToTest = ['v1.73', 'v1.73.6'];
versionsToTest.forEach(version => {
const support = kialiApi.supportedVersion(version);
expect(support).toBeUndefined();
});
});

it('Plugin not support version', () => {
const versionToTest = 'v1.70';
const support = kialiApi.supportedVersion(versionToTest);
const kialiSupported = supported[KIALI_CORE_VERSION];
expect(support).toBe(
`Kiali version supported is ${kialiSupported}, we found version ${versionToTest}`,
);
});
});
});
59 changes: 50 additions & 9 deletions plugins/kiali-backend/src/clients/KialiAPIConnector.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Logger } from 'winston';

import supported from '../kiali_supported.json';
import { KialiDetails } from '../service/config';
import { KialiFetcher } from './fetch';
import { KialiFetcher, KialiValidations, ValidationCategory } from './fetch';

export type Options = {
logger: Logger;
kiali: KialiDetails;
};

export const KIALI_CORE_VERSION = 'Kiali version';

type Status = { [K: string]: string };

interface StatusState {
status: Status;
}

export interface KialiApi {
proxy(endpoint: string, method?: string): Promise<any>;
}
Expand All @@ -21,7 +30,26 @@ export class KialiApiImpl implements KialiApi {
this.kialiFetcher = new KialiFetcher(options.kiali, options.logger);
}

async proxy(endpoint: string, method: string): Promise<any> {
supportedVersion = (version: string): string | undefined => {
this.logger.info('Validating kiali version');
const versionSupported = supported[KIALI_CORE_VERSION].replace(
/^./,
'',
).split('.');
const versionClean = version.replace(/^./, '').split('.');
this.logger.info(
`Kiali Version supported ${supported[KIALI_CORE_VERSION]}`,
);
if (
versionSupported[0] === versionClean[0] &&
versionSupported[1] === versionClean[1]
) {
return undefined;
}
return `Kiali version supported is ${supported[KIALI_CORE_VERSION]}, we found version ${version}`;
};

async proxy(endpoint: string): Promise<any> {
const authValid = await this.kialiFetcher.checkSession();
if (authValid.verify) {
this.logger.debug(
Expand All @@ -30,7 +58,7 @@ export class KialiApiImpl implements KialiApi {
}`,
);
return this.kialiFetcher
.newRequest<any>(endpoint, false, method)
.newRequest<any>(endpoint, false)
.then(resp => resp.data);
}
this.logger.debug(
Expand All @@ -43,12 +71,25 @@ export class KialiApiImpl implements KialiApi {
}

async status(): Promise<any> {
const authValid = await this.kialiFetcher.checkSession();
if (authValid.verify) {
return this.kialiFetcher
.newRequest<any>('api/status')
.then(resp => resp.data);
const validations = await this.kialiFetcher.checkSession();
if (validations.verify) {
return this.kialiFetcher.newRequest<any>('api/status').then(resp => {
const st: StatusState = resp.data;
const versionControl = this.supportedVersion(
st.status[KIALI_CORE_VERSION],
);
if (versionControl) {
const response: KialiValidations = {
verify: false,
category: ValidationCategory.versionSupported,
title: 'kiali version not supported',
message: versionControl,
};
return Promise.resolve(response);
}
return Promise.resolve(resp.data);
});
}
return Promise.resolve(authValid);
return Promise.resolve(validations);
}
}
23 changes: 22 additions & 1 deletion plugins/kiali-backend/src/clients/fetch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AxiosError } from 'axios';
import { createLogger, transports } from 'winston';

import { AuthStrategy } from './Auth';
import { KialiFetcher } from './fetch';
import { KialiFetcher, ValidationCategory } from './fetch';

const logger = createLogger({
transports: [new transports.Console({ silent: true })],
Expand All @@ -22,6 +22,7 @@ describe('kiali Fetch', () => {
});

expect(result.verify).toBeTruthy();
expect(result.category).toBe(ValidationCategory.unknown);
expect(result.message).toBeUndefined();
expect(result.missingAttributes).toBeUndefined();
expect(result.helper).toBeUndefined();
Expand All @@ -39,6 +40,7 @@ describe('kiali Fetch', () => {
});

expect(result.verify).toBeFalsy();
expect(result.category).toBe(ValidationCategory.configuration);
expect(result.message).toBeDefined();
expect(result.message).toStrictEqual(
"Attribute 'serviceAccountToken' is not in the backstage configuration",
Expand All @@ -60,6 +62,7 @@ describe('kiali Fetch', () => {
});

expect(result.verify).toBeTruthy();
expect(result.category).toBe(ValidationCategory.unknown);
expect(result.message).toBeUndefined();
expect(result.missingAttributes).toBeUndefined();
expect(result.helper).toBeUndefined();
Expand All @@ -78,6 +81,7 @@ describe('kiali Fetch', () => {
});

expect(result.verify).toBeFalsy();
expect(result.category).toBe(ValidationCategory.configuration);
expect(result.message).toBeDefined();
expect(result.message).toStrictEqual(
`Strategy ${AuthStrategy.openid} is not supported in Kiali backstage plugin yet`,
Expand Down Expand Up @@ -127,6 +131,23 @@ describe('kiali Fetch', () => {
});
});

describe('Return networking error in checkSession', () => {
it('Respond with verify category to network', async () => {
const kialiFetch = new KialiFetcher(
{ url: 'https://localhost:4000' },
logger,
);

jest.mock('./fetch', () => ({
getAuthInfo: Promise.reject({}),
}));
const validations = await kialiFetch.checkSession();
expect(validations).toBeDefined();
expect(validations.title).toBe('Error reaching Kiali');
expect(validations.category).toBe(ValidationCategory.networking);
});
});

describe('Handle Unsuccessful Response', () => {
it('Respond with a readable message with endpoint', () => {
const kialiFetch = new KialiFetcher(
Expand Down
74 changes: 50 additions & 24 deletions plugins/kiali-backend/src/clients/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,18 @@ import {
SessionInfo,
} from './Auth';

export type AuthValid = {
export enum ValidationCategory {
configuration = 'configuration',
authentication = 'authentication',
versionSupported = 'versionSupported',
networking = 'networking',
unknown = 'unknown',
}

export type KialiValidations = {
verify: boolean;
category: ValidationCategory;
title?: string;
missingAttributes?: string[];
message?: string;
helper?: string;
Expand All @@ -32,13 +42,9 @@ export class KialiFetcher {
this.kialiAuth = new KialiAuthentication(KD);
}

newRequest = async <P>(
endpoint: string,
auth: boolean = false,
method?: string,
) => {
newRequest = async <P>(endpoint: string, auth: boolean = false) => {
this.logger.info(`Query to ${endpoint}`);
return axios.request<P>(this.getRequestInit(endpoint, auth, method));
return axios.request<P>(this.getRequestInit(endpoint, auth));
};

private async getAuthInfo(): Promise<AuthInfo> {
Expand All @@ -49,9 +55,10 @@ export class KialiFetcher {
return this.kialiAuth.getSession();
}

private validateConfiguration = (auth: AuthInfo): AuthValid => {
const result: AuthValid = {
private validateConfiguration = (auth: AuthInfo): KialiValidations => {
const result: KialiValidations = {
verify: true,
category: ValidationCategory.unknown,
authData: auth,
};
switch (auth.strategy) {
Expand All @@ -63,6 +70,8 @@ export class KialiFetcher {
this.KialiDetails.serviceAccountToken === ''
) {
result.verify = false;
result.title = 'Authentication failed. Missing Configuration';
result.category = ValidationCategory.configuration;
result.message = `Attribute 'serviceAccountToken' is not in the backstage configuration`;
result.helper = `For more information follow the steps in https://janus-idp.io/plugins/kiali`;
result.missingAttributes = ['serviceAccountToken'];
Expand All @@ -71,30 +80,46 @@ export class KialiFetcher {
}
default:
result.verify = false;
result.category = ValidationCategory.configuration;
result.title = 'Authentication failed. Not supported';
result.message = `Strategy ${auth.strategy} is not supported in Kiali backstage plugin yet`;
break;
}

return result;
};

async checkSession(): Promise<AuthValid> {
let checkAuth: AuthValid = { verify: true };
async checkSession(): Promise<KialiValidations> {
let checkValidations: KialiValidations = {
verify: true,
category: ValidationCategory.unknown,
};
/*
* Get/Update AuthInformation from /api/auth/info
*/

const auth = await this.getAuthInfo();
this.kialiAuth.setAuthInfo(auth);
this.logger.info(`AuthInfo: ${JSON.stringify(auth)}`);
/*
* Check Configuration
*/
checkAuth = this.validateConfiguration(auth);
try {
const auth = await this.getAuthInfo();
this.kialiAuth.setAuthInfo(auth);
this.logger.info(`AuthInfo: ${JSON.stringify(auth)}`);
/*
* Check Configuration
*/
checkValidations = this.validateConfiguration(auth);
} catch (error: any) {
return {
verify: false,
category: ValidationCategory.networking,
title: 'Error reaching Kiali',
message: error.message || '',
helper: `Check if ${this.KialiDetails.url} works`,
};
}

/*
* Check if the actual cookie/session is valid and if the configuration is right
*/
if (checkAuth.verify && this.kialiAuth.shouldRelogin()) {
if (checkValidations.verify && this.kialiAuth.shouldRelogin()) {
this.logger.info(`User must relogin`);
await this.newRequest<AuthInfo>('api/authenticate', true)
.then(resp => {
Expand All @@ -106,11 +131,13 @@ export class KialiFetcher {
this.logger.info(`User ${session.username} logged in kiali plugin`);
})
.catch(err => {
checkAuth.verify = false;
checkAuth.message = this.handleUnsuccessfulResponse(err);
checkValidations.verify = false;
checkValidations.category = ValidationCategory.authentication;
checkValidations.title = 'Authentication failed';
checkValidations.message = this.handleUnsuccessfulResponse(err);
});
}
return checkAuth;
return checkValidations;
}

private bufferFromFileOrString(file?: string, data?: string): Buffer | null {
Expand All @@ -126,7 +153,6 @@ export class KialiFetcher {
private getRequestInit = (
endpoint: string,
auth: boolean = false,
method?: string,
): AxiosRequestConfig => {
const requestInit: AxiosRequestConfig = { timeout: TIMEOUT_FETCH };
const headers = { 'X-Auth-Type-Kiali-UI': '1' };
Expand All @@ -141,7 +167,7 @@ export class KialiFetcher {
requestInit.data = params;
requestInit.method = 'post';
} else {
requestInit.method = method ? method : 'get';
requestInit.method = 'get';
requestInit.headers = {
...headers,
Accept: 'application/json',
Expand Down
3 changes: 3 additions & 0 deletions plugins/kiali-backend/src/kiali_supported.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Kiali version": "v1.73"
}
4 changes: 2 additions & 2 deletions plugins/kiali-backend/src/service/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ describe('createRouter', () => {
expect(result.body).toEqual({
status: {
'Kiali commit hash': '72a2496cb4ed1545457a68e34fe3e81409b1611d',
'Kiali container version': 'v1.71.0-SNAPSHOT',
'Kiali container version': 'v1.73.0-SNAPSHOT',
'Kiali state': 'running',
'Kiali version': 'v1.71.0-SNAPSHOT',
'Kiali version': 'v1.73.0-SNAPSHOT',
'Mesh name': 'Istio',
'Mesh version': '1.17.1',
},
Expand Down
4 changes: 1 addition & 3 deletions plugins/kiali-backend/src/service/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ export const makeRouter = (
// curl -H "Content-type: application/json" -H "Accept: application/json" -X GET localhost:7007/api/kiali/proxy --data '{"endpoint": "api/namespaces"}'
router.post('/proxy', async (req, res) => {
const endpoint = req.body.endpoint;
const method = req.body.method;

logger.info(`Call to Kiali ${endpoint}`);
res.json(await kialiAPI.proxy(endpoint, method));
res.json(await kialiAPI.proxy(endpoint));
});

router.post('/status', async (_, res) => {
Expand Down
Loading

0 comments on commit 51a35f0

Please sign in to comment.