Skip to content

Commit

Permalink
fix: add scripts to create N number of components
Browse files Browse the repository at this point in the history
  • Loading branch information
sahil143 committed Dec 28, 2024
1 parent 69a23b0 commit e265f47
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 2 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ e2e-tests/*
commitlint.config.js
**.config.js
config/*
scripts/*
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"lint": "yarn lint:ts && yarn lint:sass",
"lint:ts": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:sass": "stylelint 'src/**/*.scss' --config .stylelintrc.json",
"script": "zx ./scripts/components.mjs",
"prepare": "husky"
},
"dependencies": {
Expand Down Expand Up @@ -98,7 +99,8 @@
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4",
"webpack-merge": "^6.0.1",
"whatwg-fetch": "^3.6.20"
"whatwg-fetch": "^3.6.20",
"zx": "^8.3.0"
},
"sideEffects": [
"*.css",
Expand Down
90 changes: 90 additions & 0 deletions scripts/components.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env zx

import {
checkSafetyThresholds,
createResource,
getCurrentNamespace,
promptForNamespace,
} from './utils.mjs';

const NumberOfComponent = 2;

const baseApplicationConfig = {
apiVersion: 'appstudio.redhat.com/v1alpha1',
kind: 'Application',
metadata: {
name: 'test-application-n-components',
namespace: 'NAMESPACE',
annotations: { 'application.thumbnail': '9' },
},
spec: { displayName: 'Testing Application (100 components)' },
};

const baseComponentConfig = {
apiVersion: 'appstudio.redhat.com/v1alpha1',
kind: 'Component',
metadata: {
annotations: {
'build.appstudio.openshift.io/pipeline': '{"name":"docker-build","bundle":"latest"}',
'build.appstudio.openshift.io/request': 'configure-pac',
'image.redhat.com/generate': '{"visibility": "public"}',
},
name: 'COMPONENT_METADATA_NAME_PLACEHOLDER',
},
spec: {
componentName: 'COMPONENT_NAME_PLACEHOLDER',
application: 'test-application-n-components',
source: {
git: {
url: 'https://github.com/sahil143/devfile-sample-code-with-quarkus',
},
},
},
};

const allConfigs = [];

// Safety check
const shouldProceed = await checkSafetyThresholds(NumberOfComponent);
if (!shouldProceed) {
console.log(chalk.blue('Operation cancelled by user'));
process.exit(0);
}

// Get and confirm namespace
const currentNs = await getCurrentNamespace();
const targetNs = await promptForNamespace(currentNs);

console.log(chalk.green('Using namespace', targetNs));

// Create application
console.log(
chalk.grey(
`Creating application '${baseApplicationConfig.spec.displayName}'(${baseApplicationConfig.metadata.name})`,
allConfigs,
),
);
baseApplicationConfig.metadata['namespace'] = targetNs;

await createResource(baseApplicationConfig, 'application');

console.log(chalk.grey(`Creating ${NumberOfComponent} component`, allConfigs));

for (let i = 1; i <= NumberOfComponent; i++) {
// Create a deep copy of the base config
const config = JSON.parse(JSON.stringify(baseComponentConfig));

// Update with unique names
config.metadata.name = `devfile-sample-code-with-quarkus-longer-name-new-${i}`;
config.metadata['namespace'] = targetNs;
config.spec.componentName = `devfile-sample-code-with-quarkus-longer-name-new-${i}`;

allConfigs.push(config);
}

// Apply each config using kubectl with JSON
for (const config of allConfigs) {
await createResource(config, 'component');
}

console.log(chalk.blue(`✨ Successfully processed ${allConfigs.length} components`));
65 changes: 65 additions & 0 deletions scripts/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const DELAY = 10000;

// Function to get current namespace
export async function getCurrentNamespace() {
try {
const result = await $`kubectl config view --minify -o jsonpath='{..namespace}'`;
return result.stdout.trim() || 'default';
} catch (error) {
return 'default';
}
}

// Function to prompt for namespace
export async function promptForNamespace(currentNs) {
console.log(chalk.blue(`Current namespace is: ${currentNs}`));
const useCurrentNs = await question(
chalk.yellow(`Do you want to use the current namespace "${currentNs}"? (y/n) `),
);

if (useCurrentNs.toLowerCase() === 'y') {
return currentNs;
}

const newNs = await question(chalk.yellow('Enter the namespace to use: '));
return newNs.trim();
}

// sleep function
export async function sleep(time) {
return await new Promise((resolve) => setTimeout(resolve, time));
}

export async function createResource(config, type = 'resource') {
try {
await $`kubectl apply --validate=false -f - <<< ${JSON.stringify(config)}`;
console.log(chalk.green(`✓ Created ${type}: ${config.metadata.name}`));
// Sleep for 10 second. Disclaimer: Do not create too many component wi
await sleep(DELAY);
} catch (error) {
console.log(chalk.red(`✗ Failed to create ${type} ${config.metadata.name}: ${error.message}`));
process.exit(1);
}
}

export async function checkSafetyThresholds(numberOfComponents) {
if (numberOfComponents > 10) {
console.log(chalk.yellow('\n CAUTION:'));
console.log(chalk.yellow(`You are about to create ${numberOfComponents} components.`));
console.log(chalk.yellow('Creating too many components in quick succession might:'));
console.log(chalk.yellow(' - Overload the API server'));
console.log(chalk.yellow(' - Trigger rate limiting'));
console.log(chalk.yellow(' - Cause failed deployments'));
console.log(chalk.yellow(`\nCurrent delay between components: ${DELAY / 1000} seconds`));

if (DELAY < 10000) {
console.log(
chalk.yellow(`\nRecommended: Use a delay of at least 10 seconds between components`),
);
}

const proceed = await question(chalk.yellow('\nDo you want to proceed? (y/N) '));
return proceed.toLowerCase() === 'y';
}
return true;
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"noFallthroughCasesInSwitch": true
},
"include": ["src/", "@types"],
"exclude": ["*.config.js", ".*.cjs", "node_modules", "config/*"]
"exclude": ["*.config.js", ".*.cjs", "node_modules", "config/*", "scripts/*"]
}
35 changes: 35 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,14 @@
"@types/qs" "*"
"@types/serve-static" "*"

"@types/fs-extra@>=11":
version "11.0.4"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.4.tgz#e16a863bb8843fba8c5004362b5a73e17becca45"
integrity sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==
dependencies:
"@types/jsonfile" "*"
"@types/node" "*"

"@types/geojson@*":
version "7946.0.14"
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613"
Expand Down Expand Up @@ -1659,6 +1667,13 @@
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==

"@types/jsonfile@*":
version "6.1.4"
resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.4.tgz#614afec1a1164e7d670b4a7ad64df3e7beb7b702"
integrity sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==
dependencies:
"@types/node" "*"

"@types/lodash-es@^4.17.12":
version "4.17.12"
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b"
Expand Down Expand Up @@ -1690,6 +1705,13 @@
dependencies:
undici-types "~5.26.4"

"@types/node@>=20":
version "22.10.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9"
integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==
dependencies:
undici-types "~6.20.0"

"@types/prop-types@*":
version "15.7.12"
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz"
Expand Down Expand Up @@ -8407,6 +8429,11 @@ undici-types@~5.26.4:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==

undici-types@~6.20.0:
version "6.20.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==

unicorn-magic@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4"
Expand Down Expand Up @@ -8924,3 +8951,11 @@ yup@^0.32.11:
nanoclone "^0.2.1"
property-expr "^2.0.4"
toposort "^2.0.2"

zx@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/zx/-/zx-8.3.0.tgz#5a4750662041c5990fad1abd02743208c6555b6b"
integrity sha512-L8mY3yfJwo3a8ZDD6f9jZzAcRWJZYcV8GauZmBxLB/aSTwaMzMIEVpPp2Kyx+7yF0gdvuxKnMxAZRft9UCawiw==
optionalDependencies:
"@types/fs-extra" ">=11"
"@types/node" ">=20"

0 comments on commit e265f47

Please sign in to comment.