Skip to content

Commit

Permalink
add secure, protect connect guide link to learning resources
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Madigan <[email protected]>
  • Loading branch information
jasonmadigan committed Nov 19, 2024
1 parent bc8a85e commit f8bca2b
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 73 deletions.
195 changes: 124 additions & 71 deletions downstream.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,116 +3,169 @@
const fs = require('fs');
const path = require('path');

// Parse command-line arguments
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');

// Define file paths
const constantsPath = path.join('src', 'constants', 'links.ts');
const localesPath = path.join('locales');
const localesPath = path.join('locales', 'en', 'plugin__kuadrant-console-plugin.json');
const consoleExtensionsPath = path.join('console-extensions.json');
const localeFile = path.join(localesPath, 'en', 'plugin__kuadrant-console-plugin.json');

const upstreamName = 'Kuadrant';
const downstreamName = 'Connectivity Link';

const upstreamDocumentation = 'https://docs.kuadrant.io';
const upstreamReleaseNotes = 'https://github.com/Kuadrant/kuadrant-operator/releases';

const downstreamDocumentation =
'https://docs.redhat.com/en/documentation/red_hat_connectivity_link/1.0';
const downstreamReleaseNotes =
'https://docs.redhat.com/html-single/release_notes_for_connectivity_link_1.0/index';

const isUpstream = process.argv.includes('--upstream');

const nameToReplace = isUpstream ? downstreamName : upstreamName;
const nameToInsert = isUpstream ? upstreamName : downstreamName;
const docsLinkToReplace = isUpstream ? downstreamDocumentation : upstreamDocumentation;
const docsLinkToInsert = isUpstream ? upstreamDocumentation : downstreamDocumentation;
const releaseNotesToReplace = isUpstream ? downstreamReleaseNotes : upstreamReleaseNotes;
const releaseNotesToInsert = isUpstream ? upstreamReleaseNotes : downstreamReleaseNotes;

function updateJsonValues(filePath, searchValue, replaceValue) {
// Replacement mappings
const replacements = {
// Direct string replacements for links.ts
[constantsPath]: {
type: 'simple',
mappings: {
// Order matters: specific URLs first to prevent partial matches
'https://docs.kuadrant.io/latest/kuadrant-operator/doc/user-guides/secure-protect-connect-single-multi-cluster/':
'https://docs.redhat.com/en/documentation/red_hat_connectivity_link/1.0/html-single/configuring_and_deploying_gateway_policies_with_connectivity_link/index',
'https://docs.kuadrant.io/latest/kuadrant-operator/doc/observability/examples/':
'https://docs.redhat.com/en/documentation/red_hat_connectivity_link/1.0/html-single/connectivity_link_observability_guide/index',
'https://docs.kuadrant.io':
'https://docs.redhat.com/en/documentation/red_hat_connectivity_link/1.0/',
'https://github.com/Kuadrant/kuadrant-operator/releases':
'https://docs.redhat.com/en/documentation/red_hat_connectivity_link/1.0/html-single/release_notes_for_connectivity_link_1.0/index',
Kuadrant: 'Connectivity Link',
},
},

// Regex-based replacements for console-extensions.json
[consoleExtensionsPath]: {
type: 'regex',
patterns: [
{
search: /%plugin__kuadrant-console-plugin~Kuadrant%/g,
replace: 'Connectivity Link',
},
],
},

// Value-only replacements for plugin__kuadrant-console-plugin.json
[localesPath]: {
type: 'value',
replaceValue: 'Connectivity Link', // Replace "Kuadrant" with "Connectivity Link" in values only
},
};

function replaceSimpleStrings(filePath, mappings) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
const jsonContent = JSON.parse(content);

let updated = false;
let content = fs.readFileSync(filePath, 'utf-8');
let updatedContent = content;
let changesMade = false;

Object.keys(jsonContent).forEach((key) => {
if (jsonContent[key].includes(searchValue)) {
jsonContent[key] = jsonContent[key].replace(new RegExp(searchValue, 'g'), replaceValue);
updated = true;
Object.entries(mappings).forEach(([search, replace]) => {
if (content.includes(search)) {
console.log(`Replacing '${search}' with '${replace}' in ${filePath}`);
updatedContent = updatedContent.split(search).join(replace);
changesMade = true;
}
});

if (updated) {
fs.writeFileSync(filePath, JSON.stringify(jsonContent, null, 2));
console.log(`Updated values in ${filePath}`);
if (changesMade) {
if (!dryRun) {
fs.writeFileSync(filePath, updatedContent, 'utf-8');
console.log(`Updated content in ${filePath}`);
} else {
console.log(`[Dry Run] Would update content in ${filePath}`);
}
} else {
console.log(`No changes made to ${filePath}`);
}
} catch (error) {
console.error(`Failed to update ${filePath}: ${error}`);
console.error(`Failed to update ${filePath}: ${error.message}`);
}
}

function updateFileContent(filePath, replacements) {
function replaceWithRegex(filePath, patterns) {
try {
let content = fs.readFileSync(filePath, 'utf-8');
let updatedContent = content;
let changesMade = false;

replacements.forEach(({ searchValue, replaceValue }) => {
updatedContent = updatedContent.replace(new RegExp(searchValue, 'g'), replaceValue);
patterns.forEach(({ search, replace }) => {
if (search.test(updatedContent)) {
console.log(`Applying regex replacement: ${search} -> ${replace} in ${filePath}`);
updatedContent = updatedContent.replace(search, replace);
changesMade = true;
}
});

if (content !== updatedContent) {
fs.writeFileSync(filePath, updatedContent);
console.log(`Updated content in ${filePath}`);
if (changesMade) {
if (!dryRun) {
// Validate JSON integrity
JSON.parse(updatedContent); // Throws if invalid
fs.writeFileSync(filePath, updatedContent, 'utf-8');
console.log(`Updated JSON content in ${filePath}`);
} else {
console.log(`[Dry Run] Would update JSON content in ${filePath}`);
}
} else {
console.log(`No changes made to ${filePath}`);
}
} catch (error) {
console.error(`Failed to update ${filePath}: ${error}`);
console.error(`Failed to update ${filePath}: ${error.message}`);
}
}

function traverseAndReplace(obj, replaceValue) {
if (typeof obj === 'string') {
return obj.includes('Kuadrant') ? obj.split('Kuadrant').join(replaceValue) : obj;
} else if (Array.isArray(obj)) {
return obj.map((item) => traverseAndReplace(item, replaceValue));
} else if (typeof obj === 'object' && obj !== null) {
const newObj = {};
Object.entries(obj).forEach(([key, value]) => {
newObj[key] = traverseAndReplace(value, replaceValue);
});
return newObj;
} else {
return obj;
}
}

function updateConsoleExtensions(filePath, searchValue, replaceValue) {
function replaceValuesInJson(filePath, replaceValue) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
const jsonContent = JSON.parse(content);
const jsonData = JSON.parse(content);

let updated = false;
const updatedJsonData = traverseAndReplace(jsonData, replaceValue);

jsonContent.forEach((item) => {
if (item.properties && item.properties.name === searchValue) {
item.properties.name = replaceValue;
updated = true;
if (JSON.stringify(jsonData) !== JSON.stringify(updatedJsonData)) {
if (!dryRun) {
const updatedContentStr = JSON.stringify(updatedJsonData, null, 2);
fs.writeFileSync(filePath, updatedContentStr, 'utf-8');
console.log(`Updated JSON content in ${filePath}`);
} else {
console.log(`[Dry Run] Would update JSON content in ${filePath}`);
}
});

if (updated) {
fs.writeFileSync(filePath, JSON.stringify(jsonContent, null, 2));
console.log(`Updated console extensions in ${filePath}`);
} else {
console.log(`No changes made to ${filePath}`);
}
} catch (error) {
console.error(`Failed to update ${filePath}: ${error}`);
console.error(`Failed to update ${filePath}: ${error.message}`);
}
}

console.log(`Updating locale files to ${isUpstream ? 'upstream' : 'downstream'}...`);
updateJsonValues(localeFile, nameToReplace, nameToInsert);

console.log(`Updating constants.links.ts to ${isUpstream ? 'upstream' : 'downstream'}...`);

updateFileContent(constantsPath, [
{ searchValue: docsLinkToReplace, replaceValue: docsLinkToInsert },
{ searchValue: releaseNotesToReplace, replaceValue: releaseNotesToInsert },
]);
if (dryRun) {
console.log('Running in Dry-Run mode. No files will be modified.');
}

console.log(`Updating console-extensions.json to ${isUpstream ? 'upstream' : 'downstream'}...`);
updateConsoleExtensions(
consoleExtensionsPath,
`%plugin__kuadrant-console-plugin~${nameToReplace}%`,
nameToInsert,
);
Object.entries(replacements).forEach(([filePath, rules]) => {
switch (rules.type) {
case 'simple':
replaceSimpleStrings(filePath, rules.mappings);
break;
case 'regex':
replaceWithRegex(filePath, rules.patterns);
break;
case 'value':
replaceValuesInJson(filePath, rules.replaceValue);
break;
default:
console.warn(`Unknown replacement type for ${filePath}`);
}
});

console.log('Update complete!');
console.log('Downstream replacement update complete!');
1 change: 1 addition & 0 deletions locales/en/plugin__kuadrant-console-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"Collapse Getting Started": "Collapse Getting Started",
"Configure via": "Configure via",
"Configured Limits": "Configured Limits",
"Configuring and deploying Gateway policies with Kuadrant": "Configuring and deploying Gateway policies with Kuadrant",
"Create": "Create",
"Create AuthPolicy": "Create AuthPolicy",
"Create DNS Policy": "Create DNS Policy",
Expand Down
11 changes: 11 additions & 0 deletions src/components/KuadrantOverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,17 @@ const KuadrantOverviewPage: React.FC = () => {
{t('View Documentation')} <ExternalLinkAltIcon />
</Text>
</StackItem>
<StackItem>
<Text
component="a"
href={EXTERNAL_LINKS.secureConnectProtect}
className="kuadrant-dashboard-resource-link"
target="_blank"
>
{t('Configuring and deploying Gateway policies with Kuadrant')}{' '}
<ExternalLinkAltIcon />
</Text>
</StackItem>
</Stack>
</FlexItem>
<Divider orientation={{ default: 'vertical' }} />
Expand Down
4 changes: 2 additions & 2 deletions src/constants/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const EXTERNAL_LINKS = {
// TODO: Update these when available for real
documentation: 'https://docs.kuadrant.io',
releaseNotes: 'https://github.com/Kuadrant/kuadrant-operator/releases',
quickStarts:
'https://docs.kuadrant.io/latest/kuadrant-operator/doc/user-guides/secure-protect-connect/',
secureConnectProtect:
'https://docs.kuadrant.io/latest/kuadrant-operator/doc/user-guides/secure-protect-connect-single-multi-cluster/',
highlights: 'https://kuadrant.io/blog/',
blog: 'https://kuadrant.io/blog/',
};

0 comments on commit f8bca2b

Please sign in to comment.