forked from opendatahub-io/odh-dashboard
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pass-through.ts
111 lines (102 loc) · 3.59 KB
/
pass-through.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import {
K8sResourceCommon,
K8sStatus,
KubeFastifyInstance,
OauthFastifyRequest,
} from '../../../types';
import { DEV_MODE } from '../../../utils/constants';
import { proxyCall, ProxyError, ProxyErrorType } from '../../../utils/httpUtils';
type PassThroughData = {
method: string;
requestData: string;
url: string;
};
export const isK8sStatus = (data: unknown): data is K8sStatus =>
(data as K8sStatus).kind === 'Status';
export const passThrough = <T extends K8sResourceCommon>(
fastify: KubeFastifyInstance,
request: OauthFastifyRequest,
data: PassThroughData,
): Promise<T | K8sStatus> => {
const { method, url } = data;
// TODO: Remove when bug is fixed - https://issues.redhat.com/browse/HAC-1825
let safeURL = url;
if (method.toLowerCase() === 'post' && !url.endsWith('selfsubjectaccessreviews')) {
// Core SDK builds the wrong path for k8s -- can't post to a resource name; remove the name from the url
// eg: POST /.../configmaps/my-config-map => POST /.../configmaps
// Note: SelfSubjectAccessReviews do not include a resource name
const urlParts = url.split('/');
const queryParams = urlParts[urlParts.length - 1].split('?');
urlParts.pop();
queryParams.shift();
safeURL = urlParts.join('/');
queryParams.unshift(safeURL);
safeURL = queryParams.join('?');
}
const updatedData = {
...data,
url: safeURL,
};
return safeURLPassThrough(fastify, request, updatedData);
};
export const safeURLPassThrough = <T extends K8sResourceCommon>(
fastify: KubeFastifyInstance,
request: OauthFastifyRequest,
data: PassThroughData,
): Promise<T | K8sStatus> => {
return proxyCall(fastify, request, data)
.then((rawData) => {
let parsedData: T | K8sStatus;
try {
parsedData = JSON.parse(rawData);
} catch (e) {
if (rawData.trim() === '404 page not found') {
// API on k8s doesn't exist, generate a status.
parsedData = {
kind: 'Status',
apiVersion: 'v1',
status: 'Failure',
message: rawData,
reason: 'NotFound',
code: 404,
};
} else {
// Likely not JSON, print the error and return the content to the client
fastify.log.error(`Parsing response error: ${e}, ${data}`);
throw { code: 500, response: data };
}
}
if (isK8sStatus(parsedData)) {
if (parsedData.status !== 'Success') {
fastify.log.warn(
`Unsuccessful status Object, ${
DEV_MODE ? JSON.stringify(parsedData, null, 2) : JSON.stringify(parsedData)
}`,
);
throw { code: parsedData.code, response: parsedData };
}
}
fastify.log.info('Successful request, returning data to caller.');
return parsedData;
})
.catch((error) => {
let errorMessage = 'Unknown error';
if (error instanceof ProxyError) {
errorMessage = error.message || errorMessage;
switch (error.proxyErrorType) {
case ProxyErrorType.CALL_FAILURE:
fastify.log.error(`Kube parsing response error: ${errorMessage}`);
throw { code: 500, response: error };
case ProxyErrorType.HTTP_FAILURE:
fastify.log.error(`Kube request error: ${errorMessage}`);
throw { code: 500, response: error };
default:
// unhandled type, fall-through
}
} else if (!(error instanceof Error)) {
errorMessage = JSON.stringify(error);
}
fastify.log.error(`Unhandled error during Kube call: ${errorMessage}`);
throw error;
});
};