Skip to content

Commit 51a35f0

Browse files
authored
fix(kiali): remove IstioConfig extra, Fix links and add kiali control (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>
1 parent 09f27b7 commit 51a35f0

36 files changed

+831
-484
lines changed

plugins/kiali-backend/__fixtures__/data/config/status.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"status": {
33
"Kiali commit hash": "72a2496cb4ed1545457a68e34fe3e81409b1611d",
4-
"Kiali container version": "v1.71.0-SNAPSHOT",
4+
"Kiali container version": "v1.73.0-SNAPSHOT",
55
"Kiali state": "running",
6-
"Kiali version": "v1.71.0-SNAPSHOT",
6+
"Kiali version": "v1.73.0-SNAPSHOT",
77
"Mesh name": "Istio",
88
"Mesh version": "1.17.1"
99
},
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { createLogger, transports } from 'winston';
2+
3+
import supported from '../kiali_supported.json';
4+
import { KIALI_CORE_VERSION, KialiApiImpl } from './KialiAPIConnector';
5+
6+
const logger = createLogger({
7+
transports: [new transports.Console({ silent: true })],
8+
});
9+
10+
const kialiApi = new KialiApiImpl({
11+
logger: logger,
12+
kiali: { url: 'https://localhost:4000' },
13+
});
14+
15+
describe('kiali Api Connector', () => {
16+
describe('Validate suported version', () => {
17+
it('Plugin support the version', () => {
18+
const versionsToTest = ['v1.73', 'v1.73.6'];
19+
versionsToTest.forEach(version => {
20+
const support = kialiApi.supportedVersion(version);
21+
expect(support).toBeUndefined();
22+
});
23+
});
24+
25+
it('Plugin not support version', () => {
26+
const versionToTest = 'v1.70';
27+
const support = kialiApi.supportedVersion(versionToTest);
28+
const kialiSupported = supported[KIALI_CORE_VERSION];
29+
expect(support).toBe(
30+
`Kiali version supported is ${kialiSupported}, we found version ${versionToTest}`,
31+
);
32+
});
33+
});
34+
});

plugins/kiali-backend/src/clients/KialiAPIConnector.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
import { Logger } from 'winston';
22

3+
import supported from '../kiali_supported.json';
34
import { KialiDetails } from '../service/config';
4-
import { KialiFetcher } from './fetch';
5+
import { KialiFetcher, KialiValidations, ValidationCategory } from './fetch';
56

67
export type Options = {
78
logger: Logger;
89
kiali: KialiDetails;
910
};
1011

12+
export const KIALI_CORE_VERSION = 'Kiali version';
13+
14+
type Status = { [K: string]: string };
15+
16+
interface StatusState {
17+
status: Status;
18+
}
19+
1120
export interface KialiApi {
1221
proxy(endpoint: string, method?: string): Promise<any>;
1322
}
@@ -21,7 +30,26 @@ export class KialiApiImpl implements KialiApi {
2130
this.kialiFetcher = new KialiFetcher(options.kiali, options.logger);
2231
}
2332

24-
async proxy(endpoint: string, method: string): Promise<any> {
33+
supportedVersion = (version: string): string | undefined => {
34+
this.logger.info('Validating kiali version');
35+
const versionSupported = supported[KIALI_CORE_VERSION].replace(
36+
/^./,
37+
'',
38+
).split('.');
39+
const versionClean = version.replace(/^./, '').split('.');
40+
this.logger.info(
41+
`Kiali Version supported ${supported[KIALI_CORE_VERSION]}`,
42+
);
43+
if (
44+
versionSupported[0] === versionClean[0] &&
45+
versionSupported[1] === versionClean[1]
46+
) {
47+
return undefined;
48+
}
49+
return `Kiali version supported is ${supported[KIALI_CORE_VERSION]}, we found version ${version}`;
50+
};
51+
52+
async proxy(endpoint: string): Promise<any> {
2553
const authValid = await this.kialiFetcher.checkSession();
2654
if (authValid.verify) {
2755
this.logger.debug(
@@ -30,7 +58,7 @@ export class KialiApiImpl implements KialiApi {
3058
}`,
3159
);
3260
return this.kialiFetcher
33-
.newRequest<any>(endpoint, false, method)
61+
.newRequest<any>(endpoint, false)
3462
.then(resp => resp.data);
3563
}
3664
this.logger.debug(
@@ -43,12 +71,25 @@ export class KialiApiImpl implements KialiApi {
4371
}
4472

4573
async status(): Promise<any> {
46-
const authValid = await this.kialiFetcher.checkSession();
47-
if (authValid.verify) {
48-
return this.kialiFetcher
49-
.newRequest<any>('api/status')
50-
.then(resp => resp.data);
74+
const validations = await this.kialiFetcher.checkSession();
75+
if (validations.verify) {
76+
return this.kialiFetcher.newRequest<any>('api/status').then(resp => {
77+
const st: StatusState = resp.data;
78+
const versionControl = this.supportedVersion(
79+
st.status[KIALI_CORE_VERSION],
80+
);
81+
if (versionControl) {
82+
const response: KialiValidations = {
83+
verify: false,
84+
category: ValidationCategory.versionSupported,
85+
title: 'kiali version not supported',
86+
message: versionControl,
87+
};
88+
return Promise.resolve(response);
89+
}
90+
return Promise.resolve(resp.data);
91+
});
5192
}
52-
return Promise.resolve(authValid);
93+
return Promise.resolve(validations);
5394
}
5495
}

plugins/kiali-backend/src/clients/fetch.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AxiosError } from 'axios';
22
import { createLogger, transports } from 'winston';
33

44
import { AuthStrategy } from './Auth';
5-
import { KialiFetcher } from './fetch';
5+
import { KialiFetcher, ValidationCategory } from './fetch';
66

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

2424
expect(result.verify).toBeTruthy();
25+
expect(result.category).toBe(ValidationCategory.unknown);
2526
expect(result.message).toBeUndefined();
2627
expect(result.missingAttributes).toBeUndefined();
2728
expect(result.helper).toBeUndefined();
@@ -39,6 +40,7 @@ describe('kiali Fetch', () => {
3940
});
4041

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

6264
expect(result.verify).toBeTruthy();
65+
expect(result.category).toBe(ValidationCategory.unknown);
6366
expect(result.message).toBeUndefined();
6467
expect(result.missingAttributes).toBeUndefined();
6568
expect(result.helper).toBeUndefined();
@@ -78,6 +81,7 @@ describe('kiali Fetch', () => {
7881
});
7982

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

134+
describe('Return networking error in checkSession', () => {
135+
it('Respond with verify category to network', async () => {
136+
const kialiFetch = new KialiFetcher(
137+
{ url: 'https://localhost:4000' },
138+
logger,
139+
);
140+
141+
jest.mock('./fetch', () => ({
142+
getAuthInfo: Promise.reject({}),
143+
}));
144+
const validations = await kialiFetch.checkSession();
145+
expect(validations).toBeDefined();
146+
expect(validations.title).toBe('Error reaching Kiali');
147+
expect(validations.category).toBe(ValidationCategory.networking);
148+
});
149+
});
150+
130151
describe('Handle Unsuccessful Response', () => {
131152
it('Respond with a readable message with endpoint', () => {
132153
const kialiFetch = new KialiFetcher(

plugins/kiali-backend/src/clients/fetch.ts

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,18 @@ import {
1212
SessionInfo,
1313
} from './Auth';
1414

15-
export type AuthValid = {
15+
export enum ValidationCategory {
16+
configuration = 'configuration',
17+
authentication = 'authentication',
18+
versionSupported = 'versionSupported',
19+
networking = 'networking',
20+
unknown = 'unknown',
21+
}
22+
23+
export type KialiValidations = {
1624
verify: boolean;
25+
category: ValidationCategory;
26+
title?: string;
1727
missingAttributes?: string[];
1828
message?: string;
1929
helper?: string;
@@ -32,13 +42,9 @@ export class KialiFetcher {
3242
this.kialiAuth = new KialiAuthentication(KD);
3343
}
3444

35-
newRequest = async <P>(
36-
endpoint: string,
37-
auth: boolean = false,
38-
method?: string,
39-
) => {
45+
newRequest = async <P>(endpoint: string, auth: boolean = false) => {
4046
this.logger.info(`Query to ${endpoint}`);
41-
return axios.request<P>(this.getRequestInit(endpoint, auth, method));
47+
return axios.request<P>(this.getRequestInit(endpoint, auth));
4248
};
4349

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

52-
private validateConfiguration = (auth: AuthInfo): AuthValid => {
53-
const result: AuthValid = {
58+
private validateConfiguration = (auth: AuthInfo): KialiValidations => {
59+
const result: KialiValidations = {
5460
verify: true,
61+
category: ValidationCategory.unknown,
5562
authData: auth,
5663
};
5764
switch (auth.strategy) {
@@ -63,6 +70,8 @@ export class KialiFetcher {
6370
this.KialiDetails.serviceAccountToken === ''
6471
) {
6572
result.verify = false;
73+
result.title = 'Authentication failed. Missing Configuration';
74+
result.category = ValidationCategory.configuration;
6675
result.message = `Attribute 'serviceAccountToken' is not in the backstage configuration`;
6776
result.helper = `For more information follow the steps in https://janus-idp.io/plugins/kiali`;
6877
result.missingAttributes = ['serviceAccountToken'];
@@ -71,30 +80,46 @@ export class KialiFetcher {
7180
}
7281
default:
7382
result.verify = false;
83+
result.category = ValidationCategory.configuration;
84+
result.title = 'Authentication failed. Not supported';
7485
result.message = `Strategy ${auth.strategy} is not supported in Kiali backstage plugin yet`;
7586
break;
7687
}
7788

7889
return result;
7990
};
8091

81-
async checkSession(): Promise<AuthValid> {
82-
let checkAuth: AuthValid = { verify: true };
92+
async checkSession(): Promise<KialiValidations> {
93+
let checkValidations: KialiValidations = {
94+
verify: true,
95+
category: ValidationCategory.unknown,
96+
};
8397
/*
8498
* Get/Update AuthInformation from /api/auth/info
8599
*/
86100

87-
const auth = await this.getAuthInfo();
88-
this.kialiAuth.setAuthInfo(auth);
89-
this.logger.info(`AuthInfo: ${JSON.stringify(auth)}`);
90-
/*
91-
* Check Configuration
92-
*/
93-
checkAuth = this.validateConfiguration(auth);
101+
try {
102+
const auth = await this.getAuthInfo();
103+
this.kialiAuth.setAuthInfo(auth);
104+
this.logger.info(`AuthInfo: ${JSON.stringify(auth)}`);
105+
/*
106+
* Check Configuration
107+
*/
108+
checkValidations = this.validateConfiguration(auth);
109+
} catch (error: any) {
110+
return {
111+
verify: false,
112+
category: ValidationCategory.networking,
113+
title: 'Error reaching Kiali',
114+
message: error.message || '',
115+
helper: `Check if ${this.KialiDetails.url} works`,
116+
};
117+
}
118+
94119
/*
95120
* Check if the actual cookie/session is valid and if the configuration is right
96121
*/
97-
if (checkAuth.verify && this.kialiAuth.shouldRelogin()) {
122+
if (checkValidations.verify && this.kialiAuth.shouldRelogin()) {
98123
this.logger.info(`User must relogin`);
99124
await this.newRequest<AuthInfo>('api/authenticate', true)
100125
.then(resp => {
@@ -106,11 +131,13 @@ export class KialiFetcher {
106131
this.logger.info(`User ${session.username} logged in kiali plugin`);
107132
})
108133
.catch(err => {
109-
checkAuth.verify = false;
110-
checkAuth.message = this.handleUnsuccessfulResponse(err);
134+
checkValidations.verify = false;
135+
checkValidations.category = ValidationCategory.authentication;
136+
checkValidations.title = 'Authentication failed';
137+
checkValidations.message = this.handleUnsuccessfulResponse(err);
111138
});
112139
}
113-
return checkAuth;
140+
return checkValidations;
114141
}
115142

116143
private bufferFromFileOrString(file?: string, data?: string): Buffer | null {
@@ -126,7 +153,6 @@ export class KialiFetcher {
126153
private getRequestInit = (
127154
endpoint: string,
128155
auth: boolean = false,
129-
method?: string,
130156
): AxiosRequestConfig => {
131157
const requestInit: AxiosRequestConfig = { timeout: TIMEOUT_FETCH };
132158
const headers = { 'X-Auth-Type-Kiali-UI': '1' };
@@ -141,7 +167,7 @@ export class KialiFetcher {
141167
requestInit.data = params;
142168
requestInit.method = 'post';
143169
} else {
144-
requestInit.method = method ? method : 'get';
170+
requestInit.method = 'get';
145171
requestInit.headers = {
146172
...headers,
147173
Accept: 'application/json',
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Kiali version": "v1.73"
3+
}

plugins/kiali-backend/src/service/router.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ describe('createRouter', () => {
5454
expect(result.body).toEqual({
5555
status: {
5656
'Kiali commit hash': '72a2496cb4ed1545457a68e34fe3e81409b1611d',
57-
'Kiali container version': 'v1.71.0-SNAPSHOT',
57+
'Kiali container version': 'v1.73.0-SNAPSHOT',
5858
'Kiali state': 'running',
59-
'Kiali version': 'v1.71.0-SNAPSHOT',
59+
'Kiali version': 'v1.73.0-SNAPSHOT',
6060
'Mesh name': 'Istio',
6161
'Mesh version': '1.17.1',
6262
},

plugins/kiali-backend/src/service/router.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ export const makeRouter = (
2222
// curl -H "Content-type: application/json" -H "Accept: application/json" -X GET localhost:7007/api/kiali/proxy --data '{"endpoint": "api/namespaces"}'
2323
router.post('/proxy', async (req, res) => {
2424
const endpoint = req.body.endpoint;
25-
const method = req.body.method;
26-
2725
logger.info(`Call to Kiali ${endpoint}`);
28-
res.json(await kialiAPI.proxy(endpoint, method));
26+
res.json(await kialiAPI.proxy(endpoint));
2927
});
3028

3129
router.post('/status', async (_, res) => {

0 commit comments

Comments
 (0)