diff --git a/downstream.js b/downstream.js
index e301f61..898f64c 100755
--- a/downstream.js
+++ b/downstream.js
@@ -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!');
diff --git a/locales/en/plugin__kuadrant-console-plugin.json b/locales/en/plugin__kuadrant-console-plugin.json
index 316983e..b79cdcf 100644
--- a/locales/en/plugin__kuadrant-console-plugin.json
+++ b/locales/en/plugin__kuadrant-console-plugin.json
@@ -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",
diff --git a/src/components/KuadrantOverviewPage.tsx b/src/components/KuadrantOverviewPage.tsx
index 9103387..a7c83de 100644
--- a/src/components/KuadrantOverviewPage.tsx
+++ b/src/components/KuadrantOverviewPage.tsx
@@ -211,6 +211,17 @@ const KuadrantOverviewPage: React.FC = () => {
{t('View Documentation')}
+
+
+ {t('Configuring and deploying Gateway policies with Kuadrant')}{' '}
+
+
+
diff --git a/src/constants/links.ts b/src/constants/links.ts
index 756af82..aec5e40 100644
--- a/src/constants/links.ts
+++ b/src/constants/links.ts
@@ -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/',
};