Skip to content

Commit 4d52a6b

Browse files
feat: process relative path in balancer
1 parent 2e6051b commit 4d52a6b

File tree

6 files changed

+116
-11
lines changed

6 files changed

+116
-11
lines changed

src/containers/Clusters/columns.tsx

+12-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {UserCard} from '../../components/User/User';
1010
import type {PreparedCluster} from '../../store/reducers/clusters/types';
1111
import {formatStorageValuesToTb} from '../../utils/dataFormatters/dataFormatters';
1212
import {createDeveloperUIMonitoringPageHref} from '../../utils/developerUI/developerUI';
13-
import {getCleanBalancerValue, removeViewerPathname} from '../../utils/parseBalancer';
13+
import {getCleanBalancerValue} from '../../utils/parseBalancer';
1414
import {clusterTabsIds, getClusterPath} from '../Cluster/utils';
1515

1616
import {COLUMNS_NAMES, COLUMNS_TITLES} from './constants';
@@ -27,9 +27,11 @@ export const CLUSTERS_COLUMNS: Column<PreparedCluster>[] = [
2727
header: COLUMNS_TITLES[COLUMNS_NAMES.TITLE],
2828
width: 230,
2929
render: ({row}) => {
30-
const {balancer, name: clusterName, use_embedded_ui: useEmbeddedUi} = row;
31-
32-
const backend = balancer && removeViewerPathname(balancer);
30+
const {
31+
name: clusterName,
32+
use_embedded_ui: useEmbeddedUi,
33+
preparedBackend: backend,
34+
} = row;
3335

3436
const clusterPath =
3537
useEmbeddedUi && backend
@@ -81,7 +83,12 @@ export const CLUSTERS_COLUMNS: Column<PreparedCluster>[] = [
8183
return versions[0] || undefined;
8284
},
8385
render: ({row}) => {
84-
const {preparedVersions, versions = [], balancer, name: clusterName} = row;
86+
const {
87+
preparedVersions,
88+
versions = [],
89+
name: clusterName,
90+
preparedBackend: backend,
91+
} = row;
8592

8693
const hasErrors = !versions.length || versions.some((item) => !item.version);
8794

@@ -99,8 +106,6 @@ export const CLUSTERS_COLUMNS: Column<PreparedCluster>[] = [
99106
};
100107
});
101108

102-
const backend = balancer && removeViewerPathname(balancer);
103-
104109
return (
105110
preparedVersions.length > 0 && (
106111
<ExternalLink

src/store/reducers/clusters/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {ExtendedMetaClusterVersion} from '../../../utils/clusterVersionColo
33

44
export interface PreparedCluster extends MetaExtendedClusterInfo {
55
preparedVersions: ExtendedMetaClusterVersion[];
6+
preparedBackend?: string;
67
}
78

89
export interface ClusterDataAggregation {

src/store/reducers/clusters/utils.ts

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getVersionMap,
55
prepareClusterVersions,
66
} from '../../../utils/clusterVersionColors';
7+
import {prepareBackendFromBalancer} from '../../../utils/parseBalancer';
78

89
import type {PreparedCluster} from './types';
910

@@ -24,5 +25,8 @@ export const prepareClustersData = (data: MetaClusters): PreparedCluster[] => {
2425
return clusters.map((cluster) => ({
2526
...cluster,
2627
preparedVersions: prepareClusterVersions(cluster.versions, versionToColor),
28+
preparedBackend: cluster.balancer
29+
? prepareBackendFromBalancer(cluster.balancer)
30+
: undefined,
2731
}));
2832
};

src/utils/__test__/parseBalancer.test.ts

+73-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
getCleanBalancerValue,
33
parseBalancer,
4+
prepareBackendFromBalancer,
45
removePort,
56
removeProtocol,
67
removeViewerPathname,
@@ -68,12 +69,17 @@ describe('removeViewerPathname', () => {
6869
});
6970
});
7071
describe('removeProtocol', () => {
71-
test('should remove protocol', () => {
72+
test('should remove protocol from start', () => {
7273
const initialValue = 'https://ydb-testing-0000.search.net:8765/viewer/json';
7374
const result = 'ydb-testing-0000.search.net:8765/viewer/json';
7475

7576
expect(removeProtocol(initialValue)).toBe(result);
7677
});
78+
test('should not remove protocol string in the middle', () => {
79+
const initialValue = 'proxy/host/https:ydb-testing-0000.search.net';
80+
81+
expect(removeProtocol(initialValue)).toBe(initialValue);
82+
});
7783
});
7884
describe('removePort', () => {
7985
test('should remove port', () => {
@@ -92,3 +98,69 @@ describe('getCleanBalancerValue', () => {
9298
expect(getCleanBalancerValue(initialValue)).toBe(result);
9399
});
94100
});
101+
describe('prepareBackendFromBalancer', () => {
102+
const windowSpy = jest.spyOn(window, 'window', 'get');
103+
104+
afterEach(() => {
105+
windowSpy.mockClear();
106+
});
107+
afterAll(() => {
108+
windowSpy.mockRestore();
109+
});
110+
111+
test('should not change full balancer value - only remove viewer pathname', () => {
112+
const initialValue = 'https://ydb-testing-0000.search.net:8765/viewer/json';
113+
const result = 'https://ydb-testing-0000.search.net:8765';
114+
115+
expect(prepareBackendFromBalancer(initialValue)).toBe(result);
116+
});
117+
118+
test('should add meta backend for relative balancer value', () => {
119+
const initialValue = '/proxy/host/ydb-testing-0000.search.net/viewer/json';
120+
const result = 'https://my-host.ru/proxy/host/ydb-testing-0000.search.net';
121+
122+
windowSpy.mockImplementation(() => {
123+
return {
124+
meta_backend: 'https://my-host.ru',
125+
} as Window & typeof globalThis;
126+
});
127+
128+
expect(prepareBackendFromBalancer(initialValue)).toBe(result);
129+
});
130+
test('should add relative meta backend for relative balancer value', () => {
131+
const initialValue = '/proxy/host/ydb-testing-0000.search.net/viewer/json';
132+
const result = '/meta/proxy/host/ydb-testing-0000.search.net';
133+
134+
windowSpy.mockImplementation(() => {
135+
return {
136+
meta_backend: '/meta',
137+
} as Window & typeof globalThis;
138+
});
139+
140+
expect(prepareBackendFromBalancer(initialValue)).toBe(result);
141+
});
142+
test('should not add empty meta backend for relative balancer value', () => {
143+
const initialValue = '/proxy/host/ydb-testing-0000.search.net/viewer/json';
144+
const result = '/proxy/host/ydb-testing-0000.search.net';
145+
146+
windowSpy.mockImplementation(() => {
147+
return {
148+
meta_backend: '',
149+
} as Window & typeof globalThis;
150+
});
151+
152+
expect(prepareBackendFromBalancer(initialValue)).toBe(result);
153+
});
154+
test('should not add undefined meta backend for relative balancer value', () => {
155+
const initialValue = '/proxy/host/ydb-testing-0000.search.net/viewer/json';
156+
const result = '/proxy/host/ydb-testing-0000.search.net';
157+
158+
windowSpy.mockImplementation(() => {
159+
return {
160+
meta_backend: undefined,
161+
} as Window & typeof globalThis;
162+
});
163+
164+
expect(prepareBackendFromBalancer(initialValue)).toBe(result);
165+
});
166+
});

src/utils/__test__/prepareBackend.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {getBackendFromNodeHost, getBackendFromRawNodeData, prepareHost} from '../prepareBackend';
22

33
describe('prepareHost', () => {
4-
test('should add vm prefix to cloud din nodes', () => {
4+
test('should add u- prefix to cloud din nodes', () => {
55
const cloudDinNodeInitialHost =
66
'vm-cc8mco0j0snqehgh7r2a-ru-central1-c-nlmw-aniq.cc8mco0j0snqehgh7r2a.ydb.mdb.cloud-preprod.net';
77
const cloudDinNodeResultHost =

src/utils/parseBalancer.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
const protocolRegex = /^http[s]?:\/\//;
2+
const viewerPathnameRegex = /\/viewer\/json$/;
3+
14
export const removeViewerPathname = (value: string) => {
2-
return value.replace(/\/viewer\/json/, '');
5+
return value.replace(viewerPathnameRegex, '');
36
};
47
export const removeProtocol = (value: string) => {
5-
return value.replace(/http[s]?:\/\//, '');
8+
return value.replace(protocolRegex, '');
69
};
710

811
export const removePort = (value: string) => {
@@ -47,3 +50,23 @@ export const parseBalancer = (rawBalancer: string): ParsedBalancer => {
4750
export const getCleanBalancerValue = (rawBalancer: string) => {
4851
return removePort(parseBalancer(rawBalancer).balancer);
4952
};
53+
54+
export function prepareBackendFromBalancer(rawBalancer: string) {
55+
const preparedBalancer = removeViewerPathname(rawBalancer);
56+
57+
// Test if balancer starts with protocol
58+
// It means it is a full url and it can be used as it is
59+
// Otherwise it is a relative path to the current meta backend
60+
if (protocolRegex.test(rawBalancer)) {
61+
return preparedBalancer;
62+
}
63+
64+
// Use meta_backend if it is defined to form backend url
65+
if (window.meta_backend) {
66+
const path = window.meta_backend + '/' + preparedBalancer;
67+
// Prevent multiple slashes in case meta_backend ends with slash or balancer starts with slash
68+
return path.replaceAll(/([^:])(\/\/+)/g, '$1/');
69+
}
70+
71+
return preparedBalancer;
72+
}

0 commit comments

Comments
 (0)