Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(config-utils): enable minor config files proxy interception #2161

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/advisor-components/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
3 changes: 2 additions & 1 deletion packages/chrome/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
3 changes: 2 additions & 1 deletion packages/components/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
5 changes: 3 additions & 2 deletions packages/config-utils/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down Expand Up @@ -62,6 +63,6 @@
"options": {
"jestConfig": "packages/config-utils/jest.config.ts"
}
},
}
}
}
13 changes: 13 additions & 0 deletions packages/config-utils/src/feo/check-outgoing-requests.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
export function matchNavigationRequest(url: string): boolean {
return !!url.match(/\/api\/chrome-service\/v1\/static\/bundles-generated\.json/);
}

export function matchSearchIndexRequest(url: string): boolean {
return !!url.match(/\/api\/chrome-service\/v1\/static\/search-index-generated\.json/);
}

export function matchServiceTilesRequest(url: string): boolean {
return !!url.match(/\/api\/chrome-service\/v1\/static\/service-tiles-generated\.json/);
}

export function isInterceptAbleRequest(url: string): boolean {
const checks = [matchNavigationRequest, matchSearchIndexRequest, matchServiceTilesRequest];
return checks.some((check) => check(url));
}
24 changes: 14 additions & 10 deletions packages/config-utils/src/feo/feo-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,6 @@ export type ServiceTile = {
frontendRef: string;
};

export type ServiceGroup = {
id: string;
tiles: ServiceTile[];
};

export type ServiceCategory = {
id: string;
groups: ServiceGroup[];
};

export type ChromeWidgetEntry = {
scope: string;
module: string;
Expand All @@ -141,3 +131,17 @@ export type CRDObject = {
export type FrontendCRD = {
objects: CRDObject[];
};

export type ServicesTilesGroupResponseEntry = {
id: string;
isGroup?: boolean;
title: string;
links: ServiceTile[];
};

export type ServicesTilesResponseEntry = {
description: string;
icon: string;
id: string;
links: ServicesTilesGroupResponseEntry[];
};
56 changes: 56 additions & 0 deletions packages/config-utils/src/feo/modify-response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import fecLogger, { LogType } from '../fec-logger';
import { matchNavigationRequest, matchSearchIndexRequest, matchServiceTilesRequest } from './check-outgoing-requests';
import { ChromeStaticSearchEntry, FrontendCRD, GeneratedBundles, ServicesTilesResponseEntry } from './feo-types';
import navigationInterceptor from './navigation-interceptor';
import searchInterceptor from './search-interceptor';
import serviceTilesInterceptor from './service-tiles-interceptor';

function isGeneratedBundles(
body: GeneratedBundles | ChromeStaticSearchEntry[] | ServicesTilesResponseEntry[],
url: string
): body is GeneratedBundles {
return matchNavigationRequest(url);
}

function isSearchIndex(
body: GeneratedBundles | ChromeStaticSearchEntry[] | ServicesTilesResponseEntry[],
url: string
): body is ChromeStaticSearchEntry[] {
return matchSearchIndexRequest(url);
}

function isServiceTiles(
body: GeneratedBundles | ChromeStaticSearchEntry[] | ServicesTilesResponseEntry[],
url: string
): body is ServicesTilesResponseEntry[] {
return matchServiceTilesRequest(url);
}

export function modifyRequest(body: string, url: string, frontendCrd: FrontendCRD): string {
// intentionally let the parse throw an error to parent to handle unfinished request chunks
const objectToModify = JSON.parse(body);
// return original if no match is found
let payload: string = body;
try {
if (isGeneratedBundles(objectToModify, url)) {
const resultBundles: GeneratedBundles = [];
objectToModify.forEach((bundle) => {
const navItems = navigationInterceptor(frontendCrd, bundle, bundle.id);
resultBundles.push({ ...bundle, navItems });
});
payload = JSON.stringify(resultBundles);
} else if (isSearchIndex(objectToModify, url)) {
const staticSearch = objectToModify as ChromeStaticSearchEntry[];
const result = searchInterceptor(staticSearch, frontendCrd);
payload = JSON.stringify(result);
} else if (isServiceTiles(objectToModify, url)) {
const staticServicesTiles = objectToModify as ServicesTilesResponseEntry[];
const result = serviceTilesInterceptor(staticServicesTiles, frontendCrd);
payload = JSON.stringify(result);
}
return payload;
} catch (error) {
fecLogger(LogType.error, `Error modifying proxy request via config interceptors: ${error}`);
return payload;
}
}
38 changes: 25 additions & 13 deletions packages/config-utils/src/feo/service-tiles-interceptor.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FrontendCRD, ServiceCategory } from './feo-types';
import { FrontendCRD, ServicesTilesResponseEntry } from './feo-types';
import serviceTilesInterceptor from './service-tiles-interceptor';

describe('Service tiles interceptor', () => {
Expand Down Expand Up @@ -38,13 +38,16 @@ describe('Service tiles interceptor', () => {
},
],
};
const remoteServiceTiles: ServiceCategory[] = [
const remoteServiceTiles: ServicesTilesResponseEntry[] = [
{
id: 'section-1',
groups: [
description: 'section 1',
icon: 'icon',
links: [
{
id: 'group-1',
tiles: [
title: 'Group 1',
links: [
{
section: 'section-1',
group: 'group-1',
Expand All @@ -63,10 +66,13 @@ describe('Service tiles interceptor', () => {
},
{
id: 'section-2',
groups: [
description: 'section 2',
icon: 'icon',
links: [
{
id: 'group-1',
tiles: [
title: 'Group 1',
links: [
{
section: 'section-2',
group: 'group-1',
Expand All @@ -78,14 +84,17 @@ describe('Service tiles interceptor', () => {
],
},
];
const expectedServiceTiles: ServiceCategory[] = [
const expectedServiceTiles: ServicesTilesResponseEntry[] = [
{
id: 'section-1',
groups: [
description: 'section 1',
icon: 'icon',
links: [
{
title: 'Group 1',
id: 'group-1',
tiles: [
remoteServiceTiles[0].groups[0].tiles[0],
links: [
remoteServiceTiles[0].links[0].links[0],
{
section: 'section-1',
group: 'group-1',
Expand All @@ -104,11 +113,14 @@ describe('Service tiles interceptor', () => {
},
{
id: 'section-2',
groups: [
description: 'section 2',
icon: 'icon',
links: [
{
title: 'Group 1',
id: 'group-1',
tiles: [
remoteServiceTiles[1].groups[0].tiles[0],
links: [
remoteServiceTiles[1].links[0].links[0],
{
section: 'section-2',
group: 'group-1',
Expand Down
12 changes: 6 additions & 6 deletions packages/config-utils/src/feo/service-tiles-interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FrontendCRD, ServiceCategory, ServiceTile } from './feo-types';
import { FrontendCRD, ServiceTile, ServicesTilesResponseEntry } from './feo-types';

function serviceTilesInterceptor(serviceCategories: ServiceCategory[], frontendCrd: FrontendCRD): ServiceCategory[] {
function serviceTilesInterceptor(serviceCategories: ServicesTilesResponseEntry[], frontendCrd: FrontendCRD): ServicesTilesResponseEntry[] {
const frontendRef = frontendCrd.objects[0].metadata.name;
let result = [...serviceCategories];

Expand All @@ -23,16 +23,16 @@ function serviceTilesInterceptor(serviceCategories: ServiceCategory[], frontendC
}, {}) ?? {};

result = result.map((category) => {
const newGroups = category.groups.map((group) => {
const newTiles = group.tiles.filter((tile) => tile.frontendRef !== frontendRef);
const newGroups = category.links.map((group) => {
const newTiles = group.links.filter((tile) => tile.frontendRef !== frontendRef);
return {
...group,
tiles: [...newTiles, ...(frontendCategories[category.id]?.[group.id] ?? [])],
links: [...newTiles, ...(frontendCategories[category.id]?.[group.id] ?? [])],
};
});
return {
...category,
groups: newGroups,
links: newGroups,
};
});

Expand Down
42 changes: 24 additions & 18 deletions packages/config-utils/src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import type { Configuration } from 'webpack-dev-server';
import { HttpsProxyAgent } from 'https-proxy-agent';
import chokidar from 'chokidar';
import cookieTransform from './cookieTransform';
import { matchNavigationRequest } from './feo/check-outgoing-requests';
import { isInterceptAbleRequest, matchNavigationRequest } from './feo/check-outgoing-requests';
import { hasFEOFeaturesEnabled, readFrontendCRD } from './feo/crd-check';
import navigationInterceptor from './feo/navigation-interceptor';
import { GeneratedBundles } from './feo/feo-types';
import fecLogger, { LogType } from './fec-logger';
import { modifyRequest } from './feo/modify-response';
import { FrontendCRD } from './feo/feo-types';

const defaultReposDir = path.join(__dirname, 'repos');

Expand Down Expand Up @@ -136,13 +136,22 @@ const proxy = ({
localApps = process.env.LOCAL_APPS,
frontendCRDPath = path.resolve(process.cwd(), 'deploy/frontend.yaml'),
}: ProxyOptions) => {
const frontendCrdRef = { current: readFrontendCRD(frontendCRDPath) };
const FEOFeaturesEnabled = hasFEOFeaturesEnabled(frontendCrdRef.current);
const frontendCrdRef: { current?: FrontendCRD } = { current: undefined };
let FEOFeaturesEnabled = false;
try {
frontendCrdRef.current = readFrontendCRD(frontendCRDPath);
FEOFeaturesEnabled = hasFEOFeaturesEnabled(frontendCrdRef.current);
} catch (e) {
fecLogger(
LogType.warn,
`FEO features are not enabled. Unable to find frontend CRD file at ${frontendCRDPath}. If you want FEO features for local development, make sure to have a "deploy/frontend.yaml" file in your project or specify its location via "frontendCRDPath" attribute.`
);
}
const proxy: ProxyConfigItem[] = [];
const majorEnv = env.split('-')[0];
const defaultLocalAppHost = process.env.LOCAL_APP_HOST || majorEnv + '.foo.redhat.com';

if (FEOFeaturesEnabled) {
if (FEOFeaturesEnabled && frontendCrdRef?.current) {
fecLogger(LogType.info, 'Watching frontend CRC file for changes');
const watcher = chokidar.watch(frontendCRDPath).on('change', () => {
fecLogger(LogType.info, 'Frontend CRD has changed, reloading the file');
Expand Down Expand Up @@ -226,7 +235,7 @@ const proxy = ({
changeOrigin: true,
autoRewrite: true,
onProxyReq: (proxyReq, req) => {
if (matchNavigationRequest(req.url)) {
if (isInterceptAbleRequest(req.url)) {
// necessary to avoid gzip encoding and issues with parsing the json body
proxyReq.setHeader('accept-encoding', 'gzip;q=0,deflate,sdch');
}
Expand All @@ -235,7 +244,7 @@ const proxy = ({
// this should reading the aggregated bundles filed generated from chrome service
// The functionality is disabled until the interceptor is ready
// eslint-disable-next-line no-constant-condition
if (matchNavigationRequest(req.url)) {
if (isInterceptAbleRequest(req.url)) {
// stub the original write function
const _write = res.write;
let body = '';
Expand All @@ -245,17 +254,14 @@ const proxy = ({

res.write = function () {
try {
const objectToModify = JSON.parse(body) as GeneratedBundles;
const resultBundles: GeneratedBundles = [];
if (FEOFeaturesEnabled) {
// these will be filled in chrome service once migration is ready to start
objectToModify.forEach((bundle) => {
const navItems = navigationInterceptor(frontendCrdRef.current, bundle, bundle.id);
resultBundles.push({ ...bundle, navItems });
});
if (FEOFeaturesEnabled && frontendCrdRef.current) {
const payload = modifyRequest(body, req.url, frontendCrdRef.current);
// content length is necessary to update to prevent JSON parsing errors in browser
res.setHeader('content-length', payload.length);
_write.call(res, payload, 'utf8');
} else {
_write.call(res, body, 'utf8');
}
const payload = JSON.stringify(resultBundles);
_write.call(res, payload, 'utf8');
return true;
} catch {
// wait for all the chunks to arrive
Expand Down
3 changes: 2 additions & 1 deletion packages/config/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
3 changes: 2 additions & 1 deletion packages/eslint-config/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
3 changes: 2 additions & 1 deletion packages/notifications/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
3 changes: 2 additions & 1 deletion packages/remediations/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
"push": true,
"preset": "conventionalcommits",
"commitMessageFormat": "chore: bump {projectName} to {version} [skip ci]"
}
},
"dependsOn": ["^version"]
},
"github": {
"executor": "@jscutlery/semver:github",
Expand Down
Loading
Loading