diff --git a/community-edition/apply/index.js b/community-edition/apply/index.mjs similarity index 50% rename from community-edition/apply/index.js rename to community-edition/apply/index.mjs index cdb48241..6c28ee98 100644 --- a/community-edition/apply/index.js +++ b/community-edition/apply/index.mjs @@ -1,10 +1,27 @@ -const { spawnSync } = require("node:child_process"); -const utils = require("../utils"); -const { execFileSync } = require("node:child_process"); +import { spawnSync, execFileSync } from "node:child_process"; +import utils from "../utils.js"; +import meow from "meow"; -spawnSync("kubectl", ["apply", "-f", "hcce.yaml"], { stdio: "inherit" }); +const cli = meow( + ` +apply — applies a Kubernetes template file to the cluster and polls until complete +Usage: -const config = utils.readConfig(); + npm run apply + npm run apply input-values.yaml + npm run apply input-values.yaml template.yaml +`, + { + importMeta: import.meta, + flags: {}, + allowUnknownFlags: false, + } +); +const templatePath = cli?.input?.[1] || "hcce.yaml"; +console.log(`applying ${templatePath}`); +spawnSync("kubectl", ["apply", "-f", templatePath], { stdio: "inherit" }); + +const config = utils.readConfig(cli); const cmd = "kubectl"; const args = ["-n", config.Namespace, "get", "deployment", "-o", "json"]; const notReady = []; diff --git a/community-edition/generate_script/index.js b/community-edition/generate_script/index.mjs similarity index 90% rename from community-edition/generate_script/index.js rename to community-edition/generate_script/index.mjs index 61bb44b0..2cd94c7e 100644 --- a/community-edition/generate_script/index.js +++ b/community-edition/generate_script/index.mjs @@ -1,9 +1,9 @@ -const crypto = require("crypto"); -const forge = require("node-forge"); -const path = require("path"); -const YAML = require("yaml"); -const pemJwk = require("pem-jwk"); -const utils = require("../utils"); +import crypto from "crypto"; +import forge from "node-forge"; +import YAML from "yaml"; +import pemJwk from "pem-jwk"; +import utils from "../utils.js"; +import meow from "meow"; // Generate a private key and public key function generateKeys() { @@ -162,10 +162,33 @@ function handleImageOverrides(processedConfig, replacedContent) { return `${yamlDocuments.map(doc => YAML.stringify(doc, {"lineWidth": 0, "directives": false})).join('---\n')}`; } +const cli = meow(` +gen-hcce — generates a Kubernetes template file for Hubs +Usage: + npm run gen-hcce + npm run gen-hcce input-values.yaml + npm run gen-hcce -- -o template.yaml + npm run gen-hcce -- input-values.yaml -o template.yaml + +Options + --output, -o write the template to this file +`, +{ + importMeta: import.meta, + flags: { + output: { + type: 'string', + default: 'hcce.yaml', + shortFlag: 'o' + }, + }, + allowUnknownFlags: false, +}); + // Main function to handle the script function main() { try { - const config = utils.readConfig(); + const config = utils.readConfig(cli); const processedConfig = YAML.parse( utils.replacePlaceholders(YAML.stringify(config), config), {"schema": "yaml-1.1"} // required to load yes/no as boolean values @@ -180,7 +203,7 @@ function main() { processedConfig.initCert = Buffer.from(pemCert).toString('base64').replace(/\n/g, ""); processedConfig.initKey = Buffer.from(pemPrivateKey).toString('base64').replace(/\n/g, ""); - // generate the hcce.yaml file + // generate the template file const template = utils.readTemplate("/generate_script", "hcce.yam"); var replacedContent = utils.replacePlaceholders(template, processedConfig); @@ -190,7 +213,7 @@ function main() { replacedContent = handleImageOverrides(processedConfig, replacedContent) - utils.writeOutputFile(replacedContent, "", "hcce.yaml"); + utils.writeOutputFile(replacedContent, "", cli.flags.output); } catch (error) { console.error("Error in main function:", error); diff --git a/community-edition/get_ip/index.js b/community-edition/get_ip/index.js deleted file mode 100644 index 70f4d92d..00000000 --- a/community-edition/get_ip/index.js +++ /dev/null @@ -1,16 +0,0 @@ -const utils = require("../utils"); -const { spawnSync } = require("node:child_process"); - -const config = utils.readConfig(); -const { stdout } = spawnSync( - "kubectl", - ["-n", config.Namespace, "get", "svc", "lb", "-o", "json"], - { stdio: ["pipe", "pipe", "inherit"] } -); -const output = JSON.parse(stdout); -const ipAddr = output.status.loadBalancer?.ingress?.[0]?.ip; -if (ipAddr) { - console.log("load balancer external IP address:", ipAddr); -} else { - console.log("load balancer not running yet:", output.status.loadBalancer); -} diff --git a/community-edition/get_ip/index.mjs b/community-edition/get_ip/index.mjs new file mode 100644 index 00000000..367ce5af --- /dev/null +++ b/community-edition/get_ip/index.mjs @@ -0,0 +1,36 @@ +import utils from "../utils.js"; +import { spawnSync } from "node:child_process"; +import meow from 'meow'; + +const cli = meow(` +get-ip — retrieves the IP address of the load balancer for the configured input values +Usage: + + npm run get-ip + npm run get-ip input-values.yaml +`, + { + importMeta: import.meta, + flags: {}, + allowUnknownFlags: false, + } +); +const config = utils.readConfig(cli); +const { stdout } = spawnSync( + "kubectl", + ["-n", config.Namespace, "get", "svc", "lb", "-o", "json"], + { stdio: ["pipe", "pipe", "inherit"] } +); +const output = JSON.parse(stdout); +const ipAddr = output.status.loadBalancer?.ingress?.[0]?.ip; +if (ipAddr) { + console.log( + `load balancer for “${config.Namespace}” external IP address:`, + ipAddr + ); +} else { + console.log( + `load balancer for “${config.Namespace}” not running yet:`, + output.status.loadBalancer + ); +} diff --git a/community-edition/package-lock.json b/community-edition/package-lock.json index cba91351..81871db6 100644 --- a/community-edition/package-lock.json +++ b/community-edition/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "inquirer": "^10.0.1", + "meow": "^13.2.0", "node-forge": "^1.3.1", "openssl-nodejs": "^1.0.5", "pem-jwk": "^2.0.0", @@ -367,6 +368,17 @@ "node": ">=8" } }, + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", diff --git a/community-edition/package.json b/community-edition/package.json index 605729bc..2e80eb00 100644 --- a/community-edition/package.json +++ b/community-edition/package.json @@ -3,19 +3,20 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "start": "echo \"Follow the steps in readme.md\nUse gen-hcce for generating your kubernetes config file, apply to apply it, and gen-ssl for adding ssl certificates\" && exit 1", - "gen-hcce": "node generate_script/index.js", - "apply": "node apply/index.js && node get_ip/index.js", - "get-ip": "node get_ip/index.js", - "gen-ssl": "node ssl_script/index.js", + "start": "echo \"Follow the steps in readme.md\nUse gen-hcce for generating your kubernetes config file, apply to update your cluster, get-ip to get the load balancer IP address, and gen-ssl for adding ssl certificates\nTo see options, use 'npm run gen-hcce -- --help' and so forth.\" && exit 1", + "gen-hcce": "node generate_script/index.mjs", + "apply": "node apply/index.mjs", + "get-ip": "node get_ip/index.mjs", + "gen-ssl": "node ssl_script/index.mjs", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", - "description": "", + "description": "scripts to set up and configure Hubs Cloud Community Edition", "dependencies": { "inquirer": "^10.0.1", + "meow": "^13.2.0", "node-forge": "^1.3.1", "openssl-nodejs": "^1.0.5", "pem-jwk": "^2.0.0", diff --git a/community-edition/readme.md b/community-edition/readme.md index 765dea8d..6dc445fc 100644 --- a/community-edition/readme.md +++ b/community-edition/readme.md @@ -127,7 +127,7 @@ then `kubectl get pods -n hcce` -If you just need to get the external IP address of your load balancer, run +If you need to get the external IP address of your load balancer, run `npm run get-ip` diff --git a/community-edition/ssl_script/index.js b/community-edition/ssl_script/index.mjs similarity index 86% rename from community-edition/ssl_script/index.js rename to community-edition/ssl_script/index.mjs index 00914863..2f7d0792 100644 --- a/community-edition/ssl_script/index.js +++ b/community-edition/ssl_script/index.mjs @@ -1,5 +1,6 @@ -const execSync = require('child_process').execSync; -const utils = require("../utils"); +import { execSync } from "child_process" +import utils from "../utils.js"; +import meow from 'meow'; function generate_ssl(config, template, url) { @@ -49,10 +50,25 @@ function generate_ssl(config, template, url) { } } +const cli = meow(` +gen-ssl — generate TLS (SSL) certificates to support HTTPS +Usage: + + npm run gen-ssl + npm run gen-ssl input-values.yaml +`, + { + importMeta: import.meta, + flags: {}, + allowUnknownFlags: false, + } +); + + function main() { try { console.log("starting script"); - const config = utils.readConfig(); + const config = utils.readConfig(cli); const template = utils.readTemplate("ssl_script", "cbb.yam"); const rootHubDomain = config.HUB_DOMAIN; generate_ssl(config, template, rootHubDomain); diff --git a/community-edition/utils.js b/community-edition/utils.js index 887c74ae..4b508ce1 100644 --- a/community-edition/utils.js +++ b/community-edition/utils.js @@ -4,9 +4,11 @@ const YAML = require("yaml"); module.exports = { // Function to read and parse YAML config file - readConfig: function readConfig() { + readConfig: function readConfig(cli) { try { - const configPath = path.join(process.cwd(), "input-values.yaml"); + const inputPath = cli?.input?.[0] || "input-values.yaml"; + console.log(`reading input from ${inputPath}`); + const configPath = path.join(process.cwd(), inputPath); const fileContents = fs.readFileSync(configPath, "utf8"); return YAML.parse(fileContents); } catch (error) { @@ -44,5 +46,5 @@ module.exports = { return template.replace(/\$(\w+)/g, (match, p1) => { return config[p1] !== undefined ? config[p1] : match; }); - } -} + }, +};