@autofleet/cli 2.11.3 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ var A=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),R=e=>{throw TypeError(e)};var O=(e,t,r)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&R("Object expected");var o,s;r&&(o=t[A("asyncDispose")]),o===void 0&&(o=t[A("dispose")],r&&(s=o)),typeof o!="function"&&R("Object not disposable"),s&&(o=function(){try{s.call(this)}catch(i){return Promise.reject(i)}}),e.push([r,o,t])}else r&&e.push([r]);return t},$=(e,t,r)=>{var o=typeof SuppressedError=="function"?SuppressedError:function(n,a,p,c){return c=Error(p),c.name="SuppressedError",c.error=n,c.suppressed=a,c},s=n=>t=r?new o(n,t,"An error was suppressed during disposal"):(r=!0,n),i=n=>{for(;n=e.pop();)try{var a=n[1]&&n[1].call(n[2]);if(n[0])return Promise.resolve(a).then(i,p=>(s(p),i()))}catch(p){s(p)}if(r)throw t};return i()};import{parseArgs as W}from"node:util";var L={name:"@autofleet/cli",version:"2.13.0",description:"",main:"dist/index.js",scripts:{start:"tsx bin/index.ts",dev:"tsup --watch",build:"tsup",linter:"eslint .",test:"vitest",coverage:"vitest --coverage"},devDependencies:{tsup:"^8.3.0",tsx:"^4.19.1"},bin:{autofleet:"./dist/index.js","autofleet-e2e":"./dist/e2e.js","git-autofleet":"./dist/git-autofleet.js"},engines:{node:">= 18.3.0"},type:"module",author:"Autofleet",license:"ISC",dependencies:{"@inquirer/prompts":"^5.0.2","p-retry":"^6.2.0"},optionalDependencies:{"@rollup/rollup-linux-x64-gnu":"*"}};var q={help:{type:"boolean",short:"h",default:!1,description:"Show help (prints this message)"},version:{type:"boolean",short:"v",default:!1,description:"Show version number"}};function B(e){e.options={...q,...e.options};let t=W(e),{values:r}=t;r.version&&(console.log(L.version),process.exit(0));let o=e.commands?`
2
+
3
+ Commands:
4
+ ${Object.entries(e.commands).map(([n,a])=>`${n.padEnd(30," ")} ${a}`).join(`
5
+ `)}
6
+ `:"",s=Math.max.apply(null,Object.values(e.options).map(({description:n})=>n.length)),i=`
7
+ ${e.binName} ${o?"[command] ":""}<options>${o}
8
+ Options:
9
+ ${Object.entries(e.options).map(([n,{description:a,type:p,short:c}])=>`${(c?`--${n}, -${c}`:`--${n}`).padEnd(30," ")} ${a.padEnd(s+10," ")} [${p}]`).join(`
10
+ `)}
11
+ `;return r.help&&(console.log(i),process.exit(0)),{...t,help:i}}import{spawn as J}from"node:child_process";var j=()=>{if(Promise.withResolvers)return Promise.withResolvers();let e,t;return{promise:new Promise((o,s)=>{e=s,t=o}),reject:e,resolve:t}};var f=async(e,t,{print:r=!0,env:o={},signal:s,shell:i}={})=>{typeof t=="boolean"&&(r=t,t=void 0);let n=new Error,a=n.stack?n.stack.replace(/^.*/," ..."):null,{promise:p,reject:c,resolve:y}=j(),l=J(e,t,{env:Object.assign(o,process.env),signal:s,shell:i});r&&(l.stdout.pipe(process.stdout),l.stderr.pipe(process.stderr));let d="",P="";l.stdout?.on("data",u=>{d+=u}),l.stderr?.on("data",u=>{P+=u});let x=r?"exit":"close";function w(u){l.removeListener(x,S),Object.assign(u,{pid:l.pid,stdout:d,stderr:P,status:null,signal:null}),c(u)}function S(u,T){l.removeListener("error",w);let C={pid:l.pid,stdout:d,stderr:P,status:u,signal:T};if(u!==0){let b=typeof t!="boolean"&&` ${t?.join(" ")}`||"",m=T?new Error(`${e}${b} exited with signal: ${T}`):new Error(`${e}${b} exited with non-zero code: ${u}`);m.stack&&a&&(m.stack+=`
12
+ ${a}`),Object.assign(m,C),c(m)}else y(C)}return l.once(x,S),l.once("error",w),p};var _e=async()=>{let{stdout:e}=await f("git",["branch","--show-current"],{print:!1});return e.trim()},M=async()=>{let{stdout:e}=await f("git",["rev-parse","--show-toplevel"],{print:!1});return e.trim()},xe=async e=>{let{stdout:t}=await f("git",["diff","origin/master..",e],{print:!1});return t},we=async e=>{try{return await f("git",["check-ignore",e],{print:!1}),!0}catch{return!1}};import{confirm as ee,input as v,select as te}from"@inquirer/prompts";import k from"node:fs";var z="SERVICE_HOST",I={prodUs:["us-autofleet-production","us-central1","autofleet-production"],prodEu:["autofleetprod","europe-west1","autofleetprod"],prodJp:["jp-autofleet-production","asia-northeast1","autofleet-japan"]},U={dev1:["dev-cluster-2","europe-west1","dev1-experiment-manager"],e2eManager:["e2e-cluster-2","europe-west1","e2e-project-1"],expManager:["af-experiment-manager","europe-west1"]},H={staging:["autofleet-staging","europe-west1-b"],loadTest:["lt-autofleet-production","asia-northeast1","load-testing-428806"]},X={osrmProd:["maps-prod","europe-west1","af-mapping"]},h={...I,...U,...H,...X},Z={staging:"europe-west1"},V=Object.keys(h),K=async e=>{let t=h[e];if(!t)throw new Error(`Cluster name ${e} does not exist!`);let[r,o,s]=t;return I[e]&&!await D(`\u274C\u274C Are you sure you want to run this command on ${e}? \u274C\u274C`,!1)?(console.log("Aborting..."),process.exit(1)):{name:r,region:o,project:s}},Re=({newFilePath:e,filePath:t,linesToReplace:r})=>{let o=k.readFileSync(t,"utf8");for(let{find:s,replace:i}of r)o=o.replace(s,i);k.writeFileSync(e,o)};async function Q(){try{let{stdout:e}=await f("kubectl",["config","current-context"],{print:!1});return e.trim()}catch{return null}}var Y=async e=>{let{name:t,region:r,project:o}=await K(e),s=`gke_${o||t}_${r}_${t}`;return await Q()===s?(console.log(`Already connected to ${e}, skipping connection to cluster...`),{name:t,region:r,project:o}):(await f("gcloud",["container","clusters","get-credentials",t,"--region",r,"--project",o||t],{print:!1}),console.log(`Switched to ${e} successfully`),{name:t,region:r,project:o})};async function Oe(){try{let{stdout:e}=await f("kubectl",["config","view","--minify","--output","jsonpath={..namespace}"],{print:!1});return e.trim()}catch{return"default"}}var $e=async({clusterName:e,variationId:t})=>(await Y(e),`--namespace=${t}`),Le=e=>{let t=e.split(`
13
+ `).filter(Boolean);t.shift();let r=t.map(o=>{let[s,i,n,a,p,c]=o.split(/(\s+)/).map(d=>d.trim()).filter(Boolean);return`${s.replace(/-/g,"_").toUpperCase()}_${z}=${a}`});return r=r.filter(o=>!o.includes("none")&&!o.includes("undefined")),r},E=(e,t)=>(e instanceof Error||(e=new Error(e)),console.error(e),t&&console.log(t),process.exit(1)),je=e=>Object.keys(U).includes(e),Me=e=>Z[e]||h[e][1];import{sep as re}from"path";Symbol.dispose??=Symbol.for("nodejs.dispose");Symbol.asyncDispose??=Symbol.for("nodejs.asyncDispose");var _,N=()=>_?.();function oe(){return process.once("beforeExit",N),{[Symbol.dispose](){process.off("beforeExit",N),_=void 0}}}async function g(e,...t){try{var r=[];try{let n=O(r,oe());let a=e(...t);_=a.cancel;return await a}catch(o){var s=o,i=!0}finally{$(r,s,i)}}catch(n){n instanceof Error&&["CancelPromptError","ExitPromptError"].includes(n.constructor.name)&&E("Cancelled! \u{1F44B}"),E(n)}}function ne(...e){return g(te,...e)}var se=e=>e.charAt(0).toUpperCase()+e.slice(1).split(/(?=[A-Z])/).join(" ");function ie(){return ne({message:"Which environment do you want to use?",choices:V.map(e=>({name:se(e),value:e})),default:"expManager"})}async function ae(){let t=(await M()).split(re).pop();return g(v,{message:"Enter the service name:",default:t})}function ce(e="default"){return g(v,{message:"Enter your simulator id (Press enter to pass):",default:e})}async function G(e="8080",t=!1){return g(v,{message:`Enter the ${t?"local ":""}port:`,default:e,validate(r){return/^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/.test(r)?!0:"Please enter a valid port number"}})}async function le(e="5432"){return G(e,!0)}var pe={cluster:ie,variationId:ce,service:ae,port:(e="8080")=>G(e),"local-port":le};async function Ne(e,t){for(let r of t){let o=typeof r=="object"?r.option:r,s=typeof r=="object"?r.defaultVal:void 0;if(typeof o!="string")throw new Error(`Invalid option ${String(o)}`);let i=pe[o];if(!i)throw new Error(`No value getter for ${String(o)}`);e[o]??=await i(s)}return e}async function D(e,t=!0){return g(ee,{message:e,default:t})}export{B as a,j as b,f as c,_e as d,M as e,xe as f,we as g,ne as h,ce as i,le as j,Ne as k,D as l,V as m,Re as n,Y as o,Oe as p,$e as q,Le as r,E as s,je as t,Me as u};
14
+ //# sourceMappingURL=chunk-IFJRGIZK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../bin/utils/parser.ts","../package.json","../bin/utils/asyncSpawn.ts","../bin/utils/promise.ts","../bin/utils/git.ts","../bin/utils/inquirer.ts","../bin/utils/index.ts"],"sourcesContent":["import { parseArgs as nativeParseArgs, ParseArgsConfig } from 'node:util';\nimport packageJson from '../../package.json' with { type: 'json' };\n\ntype ParseArgsOptionConfig = NonNullable<ParseArgsConfig['options']>[string] & { description: string };\ntype ParseArgsParams = Omit<ParseArgsConfig, 'options'> & { binName: string; options: Record<string, ParseArgsOptionConfig>; commands?: Record<string, string> };\n\nconst GLOBAL_OPTIONS = {\n help: {\n type: 'boolean',\n short: 'h',\n default: false,\n description: 'Show help (prints this message)',\n },\n version: {\n type: 'boolean',\n short: 'v',\n default: false,\n description: 'Show version number',\n },\n} satisfies ParseArgsParams['options'];\n\ntype Expanded<T extends ParseArgsParams> = T & { options: T['options'] & typeof GLOBAL_OPTIONS };\ntype Parsed<T extends ParseArgsParams> = ReturnType<typeof nativeParseArgs<Expanded<T>>> & { help: string };\n\nexport default function parseArgs<T extends ParseArgsParams = ParseArgsParams>(params: T): Parsed<T> {\n params.options = { ...GLOBAL_OPTIONS, ...params.options };\n const data = nativeParseArgs(params as Expanded<T>);\n const { values } = data;\n if ((values as { version: boolean }).version) {\n console.log(packageJson.version);\n process.exit(0);\n }\n\n const commands = !params.commands ? '' : `\n\nCommands:\n ${Object.entries(params.commands).map(([command, example]) => `${command.padEnd(30, ' ')} ${example}`).join('\\n ')}\n`;\n\n const longestDescriptionLength = Math.max.apply(null, Object.values(params.options).map(({ description }) => description.length));\n\n const help = `\n${params.binName} ${commands ? '[command] ' : ''}<options>${commands}\nOptions:\n ${Object.entries(params.options).map(([option, { description, type, short }]) => {\n const key = short ? `--${option}, -${short}` : `--${option}`;\n return `${key.padEnd(30, ' ')} ${description.padEnd(longestDescriptionLength + 10, ' ')} [${type}]`;\n }).join('\\n ')}\n`;\n\n if ((values as { help: boolean }).help) {\n console.log(help);\n process.exit(0);\n }\n\n return { ...data, help };\n}\n","{\n \"name\": \"@autofleet/cli\",\n \"version\": \"2.13.0\",\n \"description\": \"\",\n \"main\": \"dist/index.js\",\n \"scripts\": {\n \"start\": \"tsx bin/index.ts\",\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"linter\": \"eslint .\",\n \"test\": \"vitest\",\n \"coverage\": \"vitest --coverage\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.3.0\",\n \"tsx\": \"^4.19.1\"\n },\n \"bin\": {\n \"autofleet\": \"./dist/index.js\",\n \"autofleet-e2e\": \"./dist/e2e.js\",\n \"git-autofleet\": \"./dist/git-autofleet.js\"\n },\n \"engines\": {\n \"node\": \">= 18.3.0\"\n },\n \"type\": \"module\",\n \"author\": \"Autofleet\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"@inquirer/prompts\": \"^5.0.2\",\n \"p-retry\": \"^6.2.0\"\n },\n \"optionalDependencies\": {\n \"@rollup/rollup-linux-x64-gnu\": \"*\"\n }\n}\n","import { spawn } from 'node:child_process';\nimport { createDeferredPromise } from './promise.js';\n\ninterface SpawnResult {\n pid?: number;\n stdout: string;\n stderr: string;\n status: number | null;\n signal: string | null;\n}\n\nexport default async (\n command: string, args?: boolean | readonly string[], { print = true, env = {}, signal, shell }: { print?: boolean; env?: NodeJS.ProcessEnv; signal?: AbortSignal; shell?: string | boolean } = {},\n) => {\n if (typeof args === 'boolean') {\n print = args;\n args = undefined;\n }\n const stubError = new Error();\n const callerStack = stubError.stack ? stubError.stack.replace(/^.*/, ' ...') : null;\n const { promise, reject, resolve } = createDeferredPromise<SpawnResult>();\n const child = spawn(command, args, { env: Object.assign(env, process.env), signal, shell });\n if (print) {\n child.stdout.pipe(process.stdout);\n child.stderr.pipe(process.stderr);\n }\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (data) => {\n stdout += data;\n });\n child.stderr?.on('data', (data) => {\n stderr += data;\n });\n const completionEventName = print ? 'exit' : 'close';\n function errorListener(error: Error) {\n child.removeListener(completionEventName, completionListener);\n Object.assign(error, {\n pid: child.pid,\n stdout,\n stderr,\n status: null,\n signal: null,\n });\n reject(error);\n }\n function completionListener(code: number | null, signal: string | null) {\n child.removeListener('error', errorListener);\n const result: SpawnResult = {\n pid: child.pid,\n stdout,\n stderr,\n status: code,\n signal,\n };\n if (code !== 0) {\n const argumentString = (typeof args !== 'boolean' && ` ${args?.join(' ')}`) || '';\n const error = signal\n ? new Error(`${command}${argumentString} exited with signal: ${signal}`)\n : new Error(`${command}${argumentString} exited with non-zero code: ${code}`);\n if (error.stack && callerStack) {\n error.stack += `\\n${callerStack}`;\n }\n Object.assign(error, result);\n reject(error);\n } else {\n resolve(result);\n }\n }\n\n child.once(completionEventName, completionListener);\n child.once('error', errorListener);\n return promise;\n};\n","declare global {\n interface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void; // eslint-disable-line @typescript-eslint/no-explicit-any\n }\n interface PromiseConstructor {\n /**\n * Creates a new Promise and returns it in an object, along with its resolve and reject functions.\n * @returns An object with the properties `promise`, `resolve`, and `reject`.\n *\n * ```ts\n * const { promise, resolve, reject } = Promise.withResolvers<T>();\n * ```\n */\n withResolvers<T>(): PromiseWithResolvers<T>;\n }\n}\n\nexport const createDeferredPromise = <T>() => {\n if (Promise.withResolvers) {\n return Promise.withResolvers<T>();\n }\n let reject!: PromiseWithResolvers<T>['reject'];\n let resolve!: PromiseWithResolvers<T>['resolve'];\n const promise = new Promise<T>((res, rej) => {\n reject = rej;\n resolve = res;\n });\n return { promise, reject, resolve };\n};\n","import asyncSpawn from './asyncSpawn.js';\n\nexport const getCurrentBranch = async () => {\n const { stdout: currentBranch } = await asyncSpawn('git', ['branch', '--show-current'], { print: false });\n return currentBranch.trim();\n};\n\nexport const getGitPath = async () => {\n const { stdout: gitPath } = await asyncSpawn('git', ['rev-parse', '--show-toplevel'], { print: false });\n return gitPath.trim();\n};\n\nexport const getChangesOfFile = async (filePath: string) => {\n const { stdout: changes } = await asyncSpawn('git', ['diff', 'origin/master..', filePath], { print: false });\n return changes;\n};\n\nexport const isPathIgnored = async (path: string) => {\n try {\n await asyncSpawn('git', ['check-ignore', path], { print: false });\n return true;\n } catch {\n return false;\n }\n};\n","import { confirm, input, select } from '@inquirer/prompts';\nimport type { Prompt } from '@inquirer/type';\nimport { getGitPath } from './git.js';\nimport { SUPPORTED_CLUSTERS, endWithError } from './index.js';\nimport { sep } from 'path';\n\ndeclare global {\n interface SymbolConstructor {\n /** A method that is used to release resources held by an object. Called by the semantics of the `using` statement. */\n readonly dispose: unique symbol;\n /** A method that is used to asynchronously release resources held by an object. Called by the semantics of the `await using` statement. */\n readonly asyncDispose: unique symbol;\n }\n}\n// @ts-expect-error polyfill for node < 18.18\nSymbol.dispose ??= Symbol.for('nodejs.dispose');\n// @ts-expect-error polyfill for node < 18.18\nSymbol.asyncDispose ??= Symbol.for('nodejs.asyncDispose');\nlet cancelFn: (() => void) | undefined;\nconst handler = () => cancelFn?.();\nfunction addExitListener() {\n process.once('beforeExit', handler);\n return {\n [Symbol.dispose]() {\n process.off('beforeExit', handler);\n cancelFn = undefined;\n },\n };\n}\n\nasync function inquirerWrapper<Value, Config>(fn: Prompt<Value, Config>, ...params: Parameters<Prompt<Value, Config>>) {\n try {\n using _ = addExitListener();\n const result = fn(...params);\n cancelFn = result.cancel;\n return await result;\n } catch (error) {\n if (error instanceof Error && ['CancelPromptError', 'ExitPromptError'].includes(error.constructor.name)) {\n endWithError('Cancelled! 👋');\n }\n endWithError(error as Error);\n }\n}\n\nexport function safeSelect<Value>(...params: Parameters<typeof select<Value>>) {\n return inquirerWrapper(select, ...params);\n}\n\nconst splitWordAtCapital = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).split(/(?=[A-Z])/).join(' ');\n\nfunction getEnvironment() {\n return safeSelect({\n message: 'Which environment do you want to use?',\n choices: SUPPORTED_CLUSTERS.map(cluster => ({ name: splitWordAtCapital(cluster), value: cluster })),\n default: 'expManager',\n });\n}\n\nasync function getServiceName() {\n const currentServicePath = await getGitPath();\n const defaultValue = currentServicePath.split(sep).pop();\n return inquirerWrapper(input, { message: 'Enter the service name:', default: defaultValue });\n}\n\nexport function getVariationId(defaultVal = 'default') {\n return inquirerWrapper(input, { message: 'Enter your simulator id (Press enter to pass):', default: defaultVal });\n}\n\nasync function getPort(defaultVal = '8080', isLocal = false) {\n return inquirerWrapper(input, {\n message: `Enter the ${isLocal ? 'local ' : ''}port:`,\n default: defaultVal,\n validate(value) {\n // Regex source: https://stackoverflow.com/a/12968117\n if (!/^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/.test(value)) {\n return 'Please enter a valid port number';\n }\n return true;\n },\n });\n}\n\nexport async function getLocalPort(defaultVal = '5432') {\n return getPort(defaultVal, true);\n}\n\nconst VALUE_GETTER_MAP = {\n cluster: getEnvironment,\n variationId: getVariationId,\n service: getServiceName,\n port: (defaultVal = '8080') => getPort(defaultVal),\n 'local-port': getLocalPort,\n} as const;\n\nexport async function fillMissingRequiredValues<T extends { [key in keyof typeof VALUE_GETTER_MAP]?: string }>(values: T, requiredValues: (keyof T | { option: keyof T; defaultVal: string })[]) {\n for (const value of requiredValues) {\n const option = typeof value === 'object' ? value.option : value;\n const defaultVal = typeof value === 'object' ? value.defaultVal : undefined;\n if (typeof option !== 'string') {\n throw new Error(`Invalid option ${String(option)}`);\n }\n const getter = VALUE_GETTER_MAP[option as keyof typeof VALUE_GETTER_MAP];\n if (!getter) {\n throw new Error(`No value getter for ${String(option)}`);\n }\n\n values[option] ??= await getter(defaultVal) as T[keyof T & string];\n }\n return values;\n}\n\nexport async function promptForConfirmation(message: string, defaultVal = true) {\n return inquirerWrapper(confirm, { message, default: defaultVal });\n}\n","#!/usr/bin/env node\nimport fs from 'node:fs';\nimport asyncSpawn from './asyncSpawn.js';\nimport { promptForConfirmation } from './inquirer.js';\n\nconst IP_LINE_SUFFIX = 'SERVICE_HOST';\nconst PROD_CLUSTER_TO_CMD_MAP = {\n prodUs: ['us-autofleet-production', 'us-central1', 'autofleet-production'],\n prodEu: ['autofleetprod', 'europe-west1', 'autofleetprod'],\n prodJp: ['jp-autofleet-production', 'asia-northeast1', 'autofleet-japan'],\n};\nconst SIMULATION_CLUSTER_TO_CMD_MAP = {\n dev1: ['dev-cluster-2', 'europe-west1', 'dev1-experiment-manager'],\n e2eManager: ['e2e-cluster-2', 'europe-west1', 'e2e-project-1'],\n expManager: ['af-experiment-manager', 'europe-west1'],\n};\nconst STAGING_CLUSTER_TO_CMD_MAP = {\n staging: ['autofleet-staging', 'europe-west1-b'],\n loadTest: ['lt-autofleet-production', 'asia-northeast1', 'load-testing-428806'],\n};\nconst MAPPING_CLUSTER_TO_CMD_MAP = {\n osrmProd: ['maps-prod', 'europe-west1', 'af-mapping'],\n};\nconst CLUSTER_TO_CMD_MAP = {\n ...PROD_CLUSTER_TO_CMD_MAP,\n ...SIMULATION_CLUSTER_TO_CMD_MAP,\n ...STAGING_CLUSTER_TO_CMD_MAP,\n ...MAPPING_CLUSTER_TO_CMD_MAP,\n};\n\nconst CLUSTER_TO_REDIS_REGION = {\n staging: 'europe-west1',\n};\n\nexport const SUPPORTED_CLUSTERS = Object.keys(CLUSTER_TO_CMD_MAP) as (keyof typeof CLUSTER_TO_CMD_MAP)[];\n\nconst getClusterDetails = async (clusterName: string) => {\n const command = CLUSTER_TO_CMD_MAP[clusterName as keyof typeof CLUSTER_TO_CMD_MAP];\n if (!command) {\n throw new Error(`Cluster name ${clusterName} does not exist!`);\n }\n const [name, region, project] = command;\n\n if (\n PROD_CLUSTER_TO_CMD_MAP[clusterName as keyof typeof PROD_CLUSTER_TO_CMD_MAP]\n && !(await promptForConfirmation(`❌❌ Are you sure you want to run this command on ${clusterName}? ❌❌`, false))) {\n console.log('Aborting...');\n return process.exit(1);\n }\n\n return { name, region, project };\n};\n\nexport const replaceInFile = ({ newFilePath, filePath, linesToReplace }: { newFilePath: string; filePath: string; linesToReplace: { find: string; replace: string }[] }) => {\n let fileAsString = fs.readFileSync(filePath, 'utf8');\n for (const { find, replace } of linesToReplace) {\n fileAsString = fileAsString.replace(find, replace);\n }\n fs.writeFileSync(newFilePath, fileAsString);\n};\nexport async function getCurrentCluster() {\n try {\n const { stdout } = await asyncSpawn('kubectl', ['config', 'current-context'], { print: false });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\nexport const connectToCluster = async (clusterName: string) => {\n const { name, region, project } = await getClusterDetails(clusterName);\n\n const expectedContext = `gke_${project || name}_${region}_${name}`;\n const currentContext = await getCurrentCluster();\n if (currentContext === expectedContext) {\n console.log(`Already connected to ${clusterName}, skipping connection to cluster...`);\n return { name, region, project };\n }\n\n await asyncSpawn('gcloud', ['container', 'clusters', 'get-credentials', name, '--region', region, '--project', project || name], { print: false });\n\n console.log(`Switched to ${clusterName} successfully`);\n\n return { name, region, project };\n};\nexport async function getCurrentNamespace() {\n try {\n const { stdout } = await asyncSpawn('kubectl', ['config', 'view', '--minify', '--output', 'jsonpath={..namespace}'], { print: false });\n return stdout.trim();\n } catch {\n return 'default'; // If no namespace is set, it defaults to 'default'\n }\n}\nexport const connectAndGetPrefix = async ({ clusterName, variationId }: { clusterName: string; variationId: string }) => {\n await connectToCluster(clusterName);\n return `--namespace=${variationId}`;\n};\nexport const parseIps = (ips: string) => {\n const ipLines = ips.split('\\n').filter(Boolean);\n ipLines.shift();\n\n let formattedIps = ipLines.map((ipLine) => {\n const [name, _type, _clusterIp, externalIp, _port, _age] = ipLine.split(/(\\s+)/).map(s => s.trim()).filter(Boolean);\n const serviceName = name.replace(/-/g, '_').toUpperCase();\n const formattedLine = `${serviceName}_${IP_LINE_SUFFIX}=${externalIp}`;\n return formattedLine;\n });\n formattedIps = formattedIps.filter(formattedIp => !formattedIp.includes('none') && !formattedIp.includes('undefined'));\n return formattedIps;\n};\n\nexport const endWithError = (error: string | Error, helpText?: string): never => {\n if (!(error instanceof Error)) {\n error = new Error(error);\n }\n console.error(error);\n if (helpText) {\n console.log(helpText);\n }\n return process.exit(1);\n};\n\nexport const isSimulationCluster = (clusterName: string) => Object.keys(SIMULATION_CLUSTER_TO_CMD_MAP).includes(clusterName);\n\nexport const getRedisRegion = (clusterName: string) => CLUSTER_TO_REDIS_REGION[clusterName as keyof typeof CLUSTER_TO_REDIS_REGION]\n || CLUSTER_TO_CMD_MAP[clusterName as keyof typeof CLUSTER_TO_CMD_MAP][1];\n"],"mappings":"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","names":["nativeParseArgs","package_default","GLOBAL_OPTIONS","parseArgs","params","data","nativeParseArgs","values","package_default","commands","command","example","longestDescriptionLength","description","help","option","type","short","spawn","createDeferredPromise","reject","resolve","res","rej","asyncSpawn_default","command","args","print","env","signal","shell","stubError","callerStack","promise","reject","resolve","createDeferredPromise","child","spawn","stdout","stderr","data","completionEventName","errorListener","error","completionListener","code","result","argumentString","getCurrentBranch","currentBranch","asyncSpawn_default","getGitPath","gitPath","getChangesOfFile","filePath","changes","isPathIgnored","path","confirm","input","select","fs","IP_LINE_SUFFIX","PROD_CLUSTER_TO_CMD_MAP","SIMULATION_CLUSTER_TO_CMD_MAP","STAGING_CLUSTER_TO_CMD_MAP","MAPPING_CLUSTER_TO_CMD_MAP","CLUSTER_TO_CMD_MAP","CLUSTER_TO_REDIS_REGION","SUPPORTED_CLUSTERS","getClusterDetails","clusterName","command","name","region","project","promptForConfirmation","replaceInFile","newFilePath","filePath","linesToReplace","fileAsString","fs","find","replace","getCurrentCluster","stdout","asyncSpawn_default","connectToCluster","expectedContext","getCurrentNamespace","connectAndGetPrefix","variationId","parseIps","ips","ipLines","formattedIps","ipLine","_type","_clusterIp","externalIp","_port","_age","s","formattedIp","endWithError","error","helpText","isSimulationCluster","getRedisRegion","sep","cancelFn","handler","addExitListener","inquirerWrapper","fn","params","_stack","_","__using","result","_error","_hasError","__callDispose","error","endWithError","safeSelect","select","splitWordAtCapital","str","getEnvironment","SUPPORTED_CLUSTERS","cluster","getServiceName","defaultValue","getGitPath","sep","input","getVariationId","defaultVal","getPort","isLocal","value","getLocalPort","VALUE_GETTER_MAP","fillMissingRequiredValues","values","requiredValues","option","getter","promptForConfirmation","message","confirm"]}
package/dist/e2e.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{a as p,c as t,n as m,q as d,r as h,s}from"./chunk-UNZ32NZN.js";import u from"node:path";import y from"p-retry";var E=["identity-ms","vehicle-ms","ride-ms","vehicle-live-data-ms","pricing-ms","payment-ms","route-plan-ms","task-ms","audit-ms","pgweb","queue-ms","placement-ms","demand-prediction-ms","control-center-ms","setting-ms","api-gateway-ms"],f={start:'--e2eBranch=<branchName> --branches="{\\"ride-ms\\": \\"AUT-7070\\"}"',getIpsForEnv:"--variationId=<yourVariationUuid> --cluster=<dev1/e2eManager>"},_=e=>Object.keys(f).includes(e),{positionals:g,values:o,help:c}=p({strict:!0,binName:"autofleet-e2e",allowPositionals:!0,options:{e2eBranch:{type:"string",default:"master",description:"Name of e2e branch"},branches:{type:"string",default:"",description:'"ride-ms": "AUT-7070"'},cluster:{type:"string",short:"c",description:"The cluster name. One of dev1, e2eManager, expManager"},variationId:{type:"string",short:"i",description:"The variation id"}},commands:f});g.length||(console.log(c),process.exit(0));var[a]=g;if(!_(a))throw s(new Error(`Command ${a} does not exist`),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(a==="start"){let i=(o.branches?.replace("{"," ")||"").replace(/[^a-z0-9]/gi,""),r=`${u.resolve()}/bin/utils/e2e.sh`,l=`${u.resolve()}/e2e.sh`;m({newFilePath:l,filePath:r,linesToReplace:[{find:"$E2E_BRANCH_PLACE_HOLDER$",replace:o.e2eBranch},{find:"$BRANCHES_PLACE_HOLDER$",replace:o.branches},{find:"$NAME_PLACE_HOLDER$",replace:i}]}),await t("chmod",[`+x ${l} && ${l}`]),console.log("finished e2e")}var{cluster:w,variationId:v}=o;if(!w)throw s(new Error("cluster required"),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(!v)throw s(new Error("variationId required"),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");var n;try{n=await d({clusterName:w,variationId:v})}catch(e){s(e)}a==="getIpsForEnv"&&(await Promise.all(E.map(e=>t("kubectl",["annotate",n,"service",e,"cloud.google.com/load-balancer-type-"],{print:!1}))),await Promise.all(E.map(e=>t("kubectl",["patch","svc",n,e,"-p",'{"spec": {"type": "LoadBalancer"}}'],{print:!1}))),console.log("exposed services successfully. the services are now creating public ips."),await y(async()=>{let{stdout:e}=await t("kubectl",[n,"get","services"],{print:!1}),i=h(e);if(i.some(r=>r.includes("<pending>")))throw new Error("Some services are still pending");i.forEach(r=>console.log(r))},{retries:10,factor:1,maxTimeout:5e3,randomize:!0}),process.exit(0));
2
+ import{a as p,c as t,n as m,q as d,r as h,s}from"./chunk-IFJRGIZK.js";import u from"node:path";import y from"p-retry";var E=["identity-ms","vehicle-ms","ride-ms","vehicle-live-data-ms","pricing-ms","payment-ms","route-plan-ms","task-ms","audit-ms","pgweb","queue-ms","placement-ms","demand-prediction-ms","control-center-ms","setting-ms","api-gateway-ms"],f={start:'--e2eBranch=<branchName> --branches="{\\"ride-ms\\": \\"AUT-7070\\"}"',getIpsForEnv:"--variationId=<yourVariationUuid> --cluster=<dev1/e2eManager>"},_=e=>Object.keys(f).includes(e),{positionals:g,values:o,help:c}=p({strict:!0,binName:"autofleet-e2e",allowPositionals:!0,options:{e2eBranch:{type:"string",default:"master",description:"Name of e2e branch"},branches:{type:"string",default:"",description:'"ride-ms": "AUT-7070"'},cluster:{type:"string",short:"c",description:"The cluster name. One of dev1, e2eManager, expManager"},variationId:{type:"string",short:"i",description:"The variation id"}},commands:f});g.length||(console.log(c),process.exit(0));var[a]=g;if(!_(a))throw s(new Error(`Command ${a} does not exist`),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(a==="start"){let i=(o.branches?.replace("{"," ")||"").replace(/[^a-z0-9]/gi,""),r=`${u.resolve()}/bin/utils/e2e.sh`,l=`${u.resolve()}/e2e.sh`;m({newFilePath:l,filePath:r,linesToReplace:[{find:"$E2E_BRANCH_PLACE_HOLDER$",replace:o.e2eBranch},{find:"$BRANCHES_PLACE_HOLDER$",replace:o.branches},{find:"$NAME_PLACE_HOLDER$",replace:i}]}),await t("chmod",[`+x ${l} && ${l}`]),console.log("finished e2e")}var{cluster:w,variationId:v}=o;if(!w)throw s(new Error("cluster required"),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(!v)throw s(new Error("variationId required"),c),new Error("Typescript is not clever enough to understand that endWithError will exit the process");var n;try{n=await d({clusterName:w,variationId:v})}catch(e){s(e)}a==="getIpsForEnv"&&(await Promise.all(E.map(e=>t("kubectl",["annotate",n,"service",e,"cloud.google.com/load-balancer-type-"],{print:!1}))),await Promise.all(E.map(e=>t("kubectl",["patch","svc",n,e,"-p",'{"spec": {"type": "LoadBalancer"}}'],{print:!1}))),console.log("exposed services successfully. the services are now creating public ips."),await y(async()=>{let{stdout:e}=await t("kubectl",[n,"get","services"],{print:!1}),i=h(e);if(i.some(r=>r.includes("<pending>")))throw new Error("Some services are still pending");i.forEach(r=>console.log(r))},{retries:10,factor:1,maxTimeout:5e3,randomize:!0}),process.exit(0));
3
3
  //# sourceMappingURL=e2e.js.map
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as g,c as r,d as l,e as u,f as w,h as b,l as d,s as n}from"./chunk-UNZ32NZN.js";import{basename as P}from"node:path";import{randomUUID as V}from"node:crypto";var m=["premajor","preminor","prepatch","prerelease"],h=["major","minor","patch",...m],v={bumpVersion:`[${h.join("|")}]`,openPR:"Opens github UI for creating a PR from the current branch.",releaseBeta:"Bumps version if needed, and publishes a beta release to NPM."},j=e=>Object.keys(v).includes(e),y=async(e,t="")=>{let{stdout:o}=await r("npm",["version",e,"--no-git-tag-version","--preid",t],{print:!1});return await r("git",["add","package*"],{print:!1}),await r("git",["commit","-m",`${e} version: ${o}`],{print:!1}),console.log(`Created commit for version bump: ${e}. Version is now ${o}`),o},x=async()=>{let e=await u(),{default:{version:t}}=await import(`${e}/package.json`,{assert:{type:"json"},with:{type:"json"}});return t.replace(/\d+\.\d+\.\d+(?:-beta-([\w]+)?\.\d+)?/,"$1")},{positionals:$,help:p}=g({strict:!0,binName:"git autofleet",allowPositionals:!0,options:{},commands:v});$.length||(console.log(p),process.exit(0));var[s,a]=$;if(!j(s))throw n(new Error(`Command ${s} does not exist`),p),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(s==="openPR"){let[e,t]=await Promise.all([u(),l()]),c=`https://github.com/Autofleet/${P(e)}/compare/${t}?expand=1`;await r("open",[c],{print:!1}),process.exit(0)}if(s==="bumpVersion"){let e=a||await b({message:"Which version type do you want to bump?",choices:(s==="bumpVersion"?h:m).map(o=>({name:o,value:o}))});if(!e)throw n(new Error(`Must explicitly define version type.
2
+ import{a as g,c as r,d as l,e as u,f as w,h as b,l as d,s as n}from"./chunk-IFJRGIZK.js";import{basename as P}from"node:path";import{randomUUID as V}from"node:crypto";var m=["premajor","preminor","prepatch","prerelease"],h=["major","minor","patch",...m],v={bumpVersion:`[${h.join("|")}]`,openPR:"Opens github UI for creating a PR from the current branch.",releaseBeta:"Bumps version if needed, and publishes a beta release to NPM."},j=e=>Object.keys(v).includes(e),y=async(e,t="")=>{let{stdout:o}=await r("npm",["version",e,"--no-git-tag-version","--preid",t],{print:!1});return await r("git",["add","package*"],{print:!1}),await r("git",["commit","-m",`${e} version: ${o}`],{print:!1}),console.log(`Created commit for version bump: ${e}. Version is now ${o}`),o},x=async()=>{let e=await u(),{default:{version:t}}=await import(`${e}/package.json`,{assert:{type:"json"},with:{type:"json"}});return t.replace(/\d+\.\d+\.\d+(?:-beta-([\w]+)?\.\d+)?/,"$1")},{positionals:$,help:p}=g({strict:!0,binName:"git autofleet",allowPositionals:!0,options:{},commands:v});$.length||(console.log(p),process.exit(0));var[s,a]=$;if(!j(s))throw n(new Error(`Command ${s} does not exist`),p),new Error("Typescript is not clever enough to understand that endWithError will exit the process");if(s==="openPR"){let[e,t]=await Promise.all([u(),l()]),c=`https://github.com/Autofleet/${P(e)}/compare/${t}?expand=1`;await r("open",[c],{print:!1}),process.exit(0)}if(s==="bumpVersion"){let e=a||await b({message:"Which version type do you want to bump?",choices:(s==="bumpVersion"?h:m).map(o=>({name:o,value:o}))});if(!e)throw n(new Error(`Must explicitly define version type.
3
3
  Version type can be one of: ${h.join(", ")}`),p),new Error("Typescript is not clever enough to understand that endWithError will exit the process");let t=await l();["main","master"].includes(t)&&(await d("Are you sure you want to bump version on main branch?")||process.exit(0)),await y(e),process.exit(0)}if(s==="releaseBeta"){a&&!m.includes(a)&&n(new Error(`Invalid version type: ${a}
4
4
  Version must be a prerelease type. (${m.join(", ")})`),p);let e=await l();["main","master"].includes(e)&&n(new Error("Cannot release beta from main branch"),p);let c=!(await w("package.json")).split(`
5
5
  `).some(i=>/^\+\s*"version":\s*"\d+\.\d+\.\d+(?:-(?:[\w-]+\.)?\d+)?",/.test(i))||await d("Version already bumped on branch. Should version be re-bumped?"),C=c&&await x(),f=c&&await y(a||"prerelease",`beta-${C||V().split("-")[0]}`);await r("npm",["run","build"]);try{await r("npm",["publish","--tag","beta","--@autofleet:registry=https://registry.npmjs.org"])}catch(i){console.error(i),n("Failed to publish beta version")}if(f)console.log(`Published beta version with new version: ${f}`);else{let{stdout:i}=await r("npm",["info",".","version"],{print:!1});console.log(`Published beta version with existing version: ${i}`)}process.exit(0)}
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import{a as J,b as Q,c as r,d as Y,e as x,g as K,h as $,i as X,j as Z,k,m as ee,o as v,p as te,q as re,r as oe,s as c,t as ae,u as se}from"./chunk-UNZ32NZN.js";import{join as ie}from"node:path";import{randomUUID as ve}from"node:crypto";import{mkdir as ye,writeFile as Se,readFile as Ee}from"node:fs/promises";var I=".mirrord";async function ne({makeDir:e=!1}={}){let o=await x(),t=ie(o,I);return e&&await ye(t,{recursive:!0}),ie(t,"mirrord.json")}async function ce(e){let o=await ne({makeDir:!0}),t={feature:{network:{incoming:{mode:"steal",http_filter:{path_filter:"^(?!/alive)"}},outgoing:!0},fs:"read",env:!0},target:{namespace:e||ve()}};return await Se(o,JSON.stringify(t,null,2)),{mirrordConfigData:t,mirrordPath:o}}async function le(){try{let e=await ne(),o=await Ee(e,{encoding:"utf-8"});return JSON.parse(o||"{}")?.target?.namespace??""}catch{return""}}function pe(e){process.once("exit",e),process.once("SIGTERM",e),process.once("SIGINT",e)}function de(e){return e&&=e.trim(),e&&(e.startsWith("'")&&e.endsWith("'")&&(e=e.slice(1,-1)),e)}var _="livenessProbe",R="readinessProbe",me=e=>`jsonpath='{.spec.template.spec.containers[?(@.name=="worker")].${e}}'`,ue=(...e)=>`{"spec": {"template": {"spec": {"containers": [{"name": "worker",${e.map(([o,t])=>`"${o}": ${t}`).join(",")}}]}}}}`,N=async(e,o,t)=>{console.log("Will now disable health check to allow debugging.");let[{stdout:i},{stdout:s}]=await Promise.all([await r("kubectl",["get",`deployment/${t}`,e,"-o",me(_)],{print:!1}),await r("kubectl",["get",`deployment/${t}`,e,"-o",me(R)],{print:!1})]);i&&=de(i),s&&=de(s),(i||s)&&(await r("kubectl",["patch",`deployment/${t}`,e,"--patch",ue([_,"null"],[R,"null"])],{print:!1}),console.log('Health check disabled, will now start mirrord and run "npm run dev". Make sure to attach a debugger!'));let n=new AbortController;pe(async()=>{globalThis.executedExitHooks||(globalThis.executedExitHooks=!0,n.abort(),(i||s)&&(console.log("Re-enabling health check."),await r("kubectl",["patch",`deployment/${t}`,e,"--patch",`'${ue([_,i],[R,s])}'`],{print:!1,shell:!0}),console.log("health check enabled.")),process.exit(0))});try{await r("mirrord",["exec","-t",`deployment/${t}`,"-n",o,"--steal","npm","run","dev"],{signal:n.signal})}catch(a){if(a&&typeof a=="object"&&"code"in a&&a.code==="ABORT_ERR")return;c(a)}};var T=async(e,o)=>{if(await v(e),e==="expManager"||e==="dev1"){let{variationId:t}=await k({variationId:o},["variationId"]);t!==""&&(await te()===t&&(console.log(`Already connected to simulation with uuid: ${t}, skipping namespace switch...`),process.exit(0)),await r("kubectl",["config","set-context","--current",`--namespace=${t}`],{print:!1}),console.log(`Switched to simulation with uuid: ${t} successfully`))}process.exit(0)};async function xe(){try{await r("telepresence",["version"],{print:!1})}catch{c(`Telepresence is not installed. Please install it from:
2
+ import{a as J,b as Q,c as r,d as Y,e as x,g as K,h as $,i as X,j as Z,k,m as ee,o as v,p as te,q as re,r as oe,s as c,t as ae,u as se}from"./chunk-IFJRGIZK.js";import{join as ie}from"node:path";import{randomUUID as ve}from"node:crypto";import{mkdir as ye,writeFile as Se,readFile as Ee}from"node:fs/promises";var I=".mirrord";async function ne({makeDir:e=!1}={}){let o=await x(),t=ie(o,I);return e&&await ye(t,{recursive:!0}),ie(t,"mirrord.json")}async function ce(e){let o=await ne({makeDir:!0}),t={feature:{network:{incoming:{mode:"steal",http_filter:{path_filter:"^(?!/alive)"}},outgoing:!0},fs:"read",env:!0},target:{namespace:e||ve()}};return await Se(o,JSON.stringify(t,null,2)),{mirrordConfigData:t,mirrordPath:o}}async function le(){try{let e=await ne(),o=await Ee(e,{encoding:"utf-8"});return JSON.parse(o||"{}")?.target?.namespace??""}catch{return""}}function pe(e){process.once("exit",e),process.once("SIGTERM",e),process.once("SIGINT",e)}function de(e){return e&&=e.trim(),e&&(e.startsWith("'")&&e.endsWith("'")&&(e=e.slice(1,-1)),e)}var C="livenessProbe",R="readinessProbe",me=e=>`jsonpath='{.spec.template.spec.containers[?(@.name=="worker")].${e}}'`,ue=(...e)=>`{"spec": {"template": {"spec": {"containers": [{"name": "worker",${e.map(([o,t])=>`"${o}": ${t}`).join(",")}}]}}}}`,N=async(e,o,t)=>{console.log("Will now disable health check to allow debugging.");let[{stdout:i},{stdout:s}]=await Promise.all([await r("kubectl",["get",`deployment/${t}`,e,"-o",me(C)],{print:!1}),await r("kubectl",["get",`deployment/${t}`,e,"-o",me(R)],{print:!1})]);i&&=de(i),s&&=de(s),(i||s)&&(await r("kubectl",["patch",`deployment/${t}`,e,"--patch",ue([C,"null"],[R,"null"])],{print:!1}),console.log('Health check disabled, will now start mirrord and run "npm run dev". Make sure to attach a debugger!'));let n=new AbortController;pe(async()=>{globalThis.executedExitHooks||(globalThis.executedExitHooks=!0,n.abort(),(i||s)&&(console.log("Re-enabling health check."),await r("kubectl",["patch",`deployment/${t}`,e,"--patch",`'${ue([C,i],[R,s])}'`],{print:!1,shell:!0}),console.log("health check enabled.")),process.exit(0))});try{await r("mirrord",["exec","-t",`deployment/${t}`,"-n",o,"--steal","npm","run","dev"],{signal:n.signal})}catch(a){if(a&&typeof a=="object"&&"code"in a&&a.code==="ABORT_ERR")return;c(a)}};var T=async(e,o)=>{if(await v(e),e==="expManager"||e==="dev1"){let{variationId:t}=await k({variationId:o},["variationId"]);t!==""&&(await te()===t&&(console.log(`Already connected to simulation with uuid: ${t}, skipping namespace switch...`),process.exit(0)),await r("kubectl",["config","set-context","--current",`--namespace=${t}`],{print:!1}),console.log(`Switched to simulation with uuid: ${t} successfully`))}process.exit(0)};async function xe(){try{await r("telepresence",["version"],{print:!1})}catch{c(`Telepresence is not installed. Please install it from:
3
3
  https://www.telepresence.io/docs/latest/quick-start/`)}}function $e(){return $({message:"Do you want to leave the connection or create a new one?",choices:[{name:"Leave the current connection",value:"leave"},{name:"Create a new connection",value:"connect"}],default:"connect"})}async function P(e){await xe();let{cluster:o="",service:t=""}=e;await v(o);let i=await $e();if(["leave","connect"].includes(i)||c("Invalid action, how did you get here? \u{1F914}"),i==="leave"){await r("telepresence",["leave",t]),console.log("Disconnected! \u{1F44B}");return}let s=e.variationId||await X(),n=e["local-port"]&&Number.parseInt(e["local-port"],10)||Number.parseInt(await Z()||"",10);await r("telepresence",["connect",`--namespace=${s}`]),await r("telepresence",["intercept",t,"--port",n.toString(),"--env-file=./.env"]),console.log("Everything is set up! \u{1F680}"),console.log(`You can now access the service at localhost:${n}`),console.log("You can only have one connection at a time. If you want to connect to a different service, you need to leave the current connection first."),process.exit(0)}var D=async(e,o,t)=>{if(!t)throw c(new Error("service is required for exposeService"),o),new Error("Typescript is not clever enough to understand that endWithError will exit the process");await r("kubectl",["patch","svc",e,t,"-p",'{"spec": {"type": "LoadBalancer"}}']),console.log(`exposed ${t} successfully. the service is now creating an internal load balancer ip to use with vpn`),process.exit(0)};import{setTimeout as ke}from"node:timers/promises";var A=async(e,o,t,i,s)=>{let n=Number.parseInt(e["local-port"]??"5432",10);Number.isNaN(n)&&c(new Error("if defined, local-port must be a number"),i);let a=`afpass_${t}`,p="postgres",d=t.replaceAll("-","_"),u=s?`${s.replaceAll("-","_")||""}_${d}`:"postgres",l=`postgres://${p}:${a}@localhost:${n}/${u}?&nickname=var_${t}`;console.log(`Forwarding db to local port ${n}.
4
4
  access the DB at ${l}
5
5
  Press ctrl+c to stop.`);let f=` DB_USERNAME=${p}
6
6
  DB_PASSWORD=${a}
7
7
  DB_NAME=${s?u:`<service_name>_${d}`}`;console.log(`Generated database environment for local development:
8
- `,f),ke(1500).then(()=>r("open",[l],{print:!1})).catch(()=>null),await r("kubectl",[o,"port-forward",`statefulset/p${t}-postgresql`,`${n}:5432`],{print:!1}),process.exit(0)};var M=async(e,o,t,i)=>{let s=Number.parseInt(e.port??"8080",10),n=Number.parseInt(e["local-port"]??"",10)||s;i||c(new Error("service is required for forwardService"),t),(!s||Number.isNaN(s))&&c(new Error("port is required and must be a numbers"),t),n&&Number.isNaN(n)&&c(new Error("local-port must be a number"),t);let{stdout:a}=await r("kubectl",["get","pods",o,"-l",`service=${i}`,"-o",'jsonpath="{.items[0].metadata.name}"'],{print:!1});a&&=a.trim(),a||c(new Error(`No pods found for service ${i}`)),a.startsWith('"')&&a.endsWith('"')&&(a=a.slice(1,-1)),console.log(`Found pod ${a}, serving locally on port ${n} from remote port ${s}.
9
- Press ctrl+c to stop.`),await r("kubectl",["port-forward",o,a,`${n}:${s}`],{print:!1}),process.exit(0)};var O=async e=>{let{stdout:o}=await r("kubectl",[e,"get","services"],{print:!1});oe(o).forEach(i=>console.log(i)),process.exit(0)};var W=async(e,o)=>{let t="simulation-cluster-front";await r("kubectl",["annotate",e,"service",t,"cloud.google.com/load-balancer-type-"]),await r("kubectl",["patch","svc",e,t,"-p",'{"spec": {"type": "LoadBalancer"}}']),await r("kubectl",["create",e,"rolebinding","admin","--clusterrole=cluster-admin",`--serviceaccount=${o}:default`]),console.log(`Successfully exposed ${t} and added role binding to dispatch simulations`),process.exit(0)};var F=async()=>{let e=i=>["get","secret","rabbitmq-default-user","-o",`jsonpath="{.data.${i}}"`],[{stdout:o},{stdout:t}]=await Promise.all([r("kubectl",e("username"),{print:!1}),r("kubectl",e("password"),{print:!1})]);console.log(`username: ${Buffer.from(o,"base64").toString("ascii")}`),console.log(`password: ${Buffer.from(t,"base64").toString("ascii")}`),process.exit(0)};import{basename as Ie}from"node:path";import{cwd as Pe}from"node:process";var V=async e=>{let o=Ie(Pe()),[t,i]=await Promise.all([Y(),r("uname",["-m"],{print:!1})]),s=i.stdout.trim(),n=`${new Date().getHours().toString().padStart(2,"0")}-${new Date().getMinutes().toString().padStart(2,"0")}-${new Date().getSeconds().toString().padStart(2,"0")}`,a=`gcr.io/autofleetprod/${o}:${t}-${n}`;console.log(`Building and pushing image ${a}`),await r("docker",["build",".",...s==="x86_64"?[]:["--platform","linux/amd64"],"-t",a,"--build-arg",`NPM_TOKEN=${process.env.NPM_TOKEN}`]),await r("docker",["push",a]);let{stdout:d}=await r("kubectl",["describe","pod",e,"-l",`service=${o}`],{print:!1});d.includes("Init Containers:")&&await r("kubectl",["patch",`deployment/${o}`,e,"--patch",`{"spec": {"template": {"spec": {"initContainers": [{"name": "init","image": "${a}"}]}}}}`]),await r("kubectl",["set","image",`deployment/${o}`,`worker=${a}`,e]),await r("kubectl",["rollout","status","deployments",o,e]),process.exit(0)};import{basename as Ne}from"node:path";import{EOL as fe}from"node:os";import{resolve as Ce}from"node:path";import{readFile as _e,writeFile as Re}from"node:fs/promises";async function L(e,o,t){let i=Ce(e,".env"),n=(await _e(i,"utf8")).split(fe),a=`(?<!#\\s*)${o}(?==)`,p=n.find(u=>u.match(a));if(p?.split("=").at(-1)===t)return!1;let d=p?n.indexOf(p):-1;return d!==-1?n.splice(d,1,`${o}=${t}`):n.push(`${o}=${t}`),await Re(i,n.join(fe)),!0}var B=async(e,o,t)=>{let i="LOCAL_ENV_NAME",s="api-gateway-ms",n="control-center-ms",a=o==="staging"?"staging":`simulator-${t}`,p=await x();Ne(p)!=="control-center"&&c(new Error("The `localDev` command must be run from the control-center repository"));let{stdout:d}=await r("kubectl",["get","ingress",`${s}-ingress`,e,"-o",'jsonpath="{.status.loadBalancer.ingress[0].ip}"'],{print:!1});d||c(new Error(`The IP of the Load balancer for ${s} was not found`));let u=await L(p,"API_GATEWAY_MS_SERVICE_HOST",d.replace(/"/g,"")),l=await L(p,i,a),f=`${u?`Updated .env file to use ${s} IP (${d}).
8
+ `,f),ke(1500).then(()=>r("open",[l],{print:!1})).catch(()=>null),await r("kubectl",[o,"port-forward",`statefulset/p${t}-postgresql`,`${n}:5432`],{print:!1}),process.exit(0)};var O=async(e,o,t,i)=>{let s=Number.parseInt(e.port??"8080",10),n=Number.parseInt(e["local-port"]??"",10)||s;i||c(new Error("service is required for forwardService"),t),(!s||Number.isNaN(s))&&c(new Error("port is required and must be a numbers"),t),n&&Number.isNaN(n)&&c(new Error("local-port must be a number"),t);let{stdout:a}=await r("kubectl",["get","pods",o,"-l",`service=${i}`,"-o",'jsonpath="{.items[0].metadata.name}"'],{print:!1});a&&=a.trim(),a||c(new Error(`No pods found for service ${i}`)),a.startsWith('"')&&a.endsWith('"')&&(a=a.slice(1,-1)),console.log(`Found pod ${a}, serving locally on port ${n} from remote port ${s}.
9
+ Press ctrl+c to stop.`),await r("kubectl",["port-forward",o,a,`${n}:${s}`],{print:!1}),process.exit(0)};var M=async e=>{let{stdout:o}=await r("kubectl",[e,"get","services"],{print:!1});oe(o).forEach(i=>console.log(i)),process.exit(0)};var W=async(e,o)=>{let t="simulation-cluster-front";await r("kubectl",["annotate",e,"service",t,"cloud.google.com/load-balancer-type-"]),await r("kubectl",["patch","svc",e,t,"-p",'{"spec": {"type": "LoadBalancer"}}']),await r("kubectl",["create",e,"rolebinding","admin","--clusterrole=cluster-admin",`--serviceaccount=${o}:default`]),console.log(`Successfully exposed ${t} and added role binding to dispatch simulations`),process.exit(0)};var F=async()=>{let e=i=>["get","secret","rabbitmq-default-user","-o",`jsonpath="{.data.${i}}"`],[{stdout:o},{stdout:t}]=await Promise.all([r("kubectl",e("username"),{print:!1}),r("kubectl",e("password"),{print:!1})]);console.log(`username: ${Buffer.from(o,"base64").toString("ascii")}`),console.log(`password: ${Buffer.from(t,"base64").toString("ascii")}`),process.exit(0)};import{basename as Ie}from"node:path";import{cwd as Pe}from"node:process";var V=async e=>{let o=Ie(Pe()),[t,i]=await Promise.all([Y(),r("uname",["-m"],{print:!1})]),s=i.stdout.trim(),n=`${new Date().getHours().toString().padStart(2,"0")}-${new Date().getMinutes().toString().padStart(2,"0")}-${new Date().getSeconds().toString().padStart(2,"0")}`,a=`gcr.io/autofleetprod/${o}:${t}-${n}`;console.log(`Building and pushing image ${a}`),await r("docker",["build",".",...s==="x86_64"?[]:["--platform","linux/amd64"],"-t",a,"--build-arg",`NPM_TOKEN=${process.env.NPM_TOKEN}`]),await r("docker",["push",a]);let{stdout:d}=await r("kubectl",["describe","pod",e,"-l",`service=${o}`],{print:!1});d.includes("Init Containers:")&&await r("kubectl",["patch",`deployment/${o}`,e,"--patch",`{"spec": {"template": {"spec": {"initContainers": [{"name": "init","image": "${a}"}]}}}}`]),await r("kubectl",["set","image",`deployment/${o}`,`worker=${a}`,e]),await r("kubectl",["rollout","status","deployments",o,e]),process.exit(0)};import{basename as Ne}from"node:path";import{EOL as fe}from"node:os";import{resolve as _e}from"node:path";import{readFile as Ce,writeFile as Re}from"node:fs/promises";async function L(e,o,t){let i=_e(e,".env"),n=(await Ce(i,"utf8")).split(fe),a=`(?<!#\\s*)${o}(?==)`,p=n.find(u=>u.match(a));if(p?.split("=").at(-1)===t)return!1;let d=p?n.indexOf(p):-1;return d!==-1?n.splice(d,1,`${o}=${t}`):n.push(`${o}=${t}`),await Re(i,n.join(fe)),!0}var B=async(e,o,t)=>{let i="LOCAL_ENV_NAME",s="api-gateway-ms",n="control-center-ms",a=o==="staging"?"staging":`simulator-${t}`,p=await x();Ne(p)!=="control-center"&&c(new Error("The `localDev` command must be run from the control-center repository"));let{stdout:d}=await r("kubectl",["get","ingress",`${s}-ingress`,e,"-o",'jsonpath="{.status.loadBalancer.ingress[0].ip}"'],{print:!1});d||c(new Error(`The IP of the Load balancer for ${s} was not found`));let u=await L(p,"API_GATEWAY_MS_SERVICE_HOST",d.replace(/"/g,"")),l=await L(p,i,a),f=`${u?`Updated .env file to use ${s} IP (${d}).
10
10
  `:""}${l?`Updated .env file ${i} to ${a} (used for firebase setup).
11
11
  `:""}Port-forwarding of ${n} will now start to port 8085.
12
- Press ctrl+c to stop.`;console.log(f),await r("kubectl",["port-forward",e,`svc/${n}`,"8085:80"],{print:!1}),process.exit(0)};import{resolve as Te}from"node:path";import{readFile as De,writeFile as Ae}from"node:fs/promises";async function Me(e){if(await K(I))return;let t=Te(e,"..","..",".gitignore"),s=(await De(t,"utf8")).split(`
12
+ Press ctrl+c to stop.`;console.log(f),await r("kubectl",["port-forward",e,`svc/${n}`,"8085:80"],{print:!1}),process.exit(0)};import{resolve as Te}from"node:path";import{readFile as De,writeFile as Ae}from"node:fs/promises";async function Oe(e){if(await K(I))return;let t=Te(e,"..","..",".gitignore"),s=(await De(t,"utf8")).split(`
13
13
  `).filter(Boolean);s.push(I),await Ae(t,`${s.join(`
14
14
  `)}
15
- `)}var U=async e=>{let{mirrordConfigData:o,mirrordPath:t}=await ce(e);await Me(t),console.log("Wrote the default mirrord config for the requested variation ID",{mirrordConfigData:o}),process.exit(0)};import*as ge from"node:path";import*as we from"node:fs";import*as he from"node:os";var Oe=`
15
+ `)}var U=async e=>{let{mirrordConfigData:o,mirrordPath:t}=await ce(e);await Oe(t),console.log("Wrote the default mirrord config for the requested variation ID",{mirrordConfigData:o}),process.exit(0)};import*as ge from"node:path";import*as we from"node:fs";import*as he from"node:os";var Me=`
16
16
  services:
17
17
  redis:
18
18
  image: redis:6
@@ -45,11 +45,40 @@ services:
45
45
  - POSTGRES_USER=postgres
46
46
  - POSTGRES_PASSWORD=postgres
47
47
 
48
+ elasticsearch:
49
+ image: docker.elastic.co/elasticsearch/elasticsearch:8.8.1
50
+ ports:
51
+ - "9200:9200"
52
+ - "9300:9300"
53
+ environment:
54
+ - discovery.type=single-node
55
+ - xpack.security.enabled=false
56
+ - xpack.security.transport.ssl.enabled=false
57
+ - xpack.security.http.ssl.enabled=false
58
+ - ES_JAVA_OPTS=-Xms1g -Xmx1g
59
+ volumes:
60
+ - elasticsearch_data:/usr/share/elasticsearch/data
61
+ ulimits:
62
+ memlock:
63
+ soft: -1
64
+ hard: -1
65
+ mem_limit: 2g
66
+
67
+ kibana:
68
+ image: docker.elastic.co/kibana/kibana:8.8.1
69
+ ports:
70
+ - "5601:5601"
71
+ environment:
72
+ - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
73
+ depends_on:
74
+ - elasticsearch
75
+
48
76
  volumes:
49
77
  redis_data:
50
78
  rabbitmq_data:
51
79
  postgres_data:
52
- `,j=async()=>{let e=ge.join(he.tmpdir(),"docker-compose.yml");we.writeFileSync(e,Oe),await r("docker-compose",["-f",e,"up","-d"],{print:!1}),console.log("--------------------------------------------------------------------------------"),console.log(`Successfully started the services:
53
- `),console.log("redis: localhost:6379 \u{1F680}"),console.log("postgres: localhost:5432, user: postgres, password: postgres \u{1F418}"),console.log("rabbitmq: localhost:5672, user: guest, password: guest \u{1F407}"),process.exit(0)};import{spawn as We}from"node:child_process";var q=async e=>{ae(e)&&(console.error("Connecting to Redis is not supported for simulation clusters (need to be added)"),process.exit(1));let{project:o,name:t}=await v(e),i=se(e),{stdout:s}=await r("gcloud",["redis","instances","list","--region",i,"--project",o||t,"--format","json"],{print:!1}),n;try{n=JSON.parse(s)}catch(l){console.error("Failed to parse redis instances",{redisInstances:s,e:l}),process.exit(1)}let a=Object.fromEntries(n.map(l=>{let f=l.name.split("/");return[l.displayName||f?.at(-1)||l.name,l.host]})),p=await $({message:"which redis instance do you want to connect to?",choices:Object.entries(a).map(([l,f])=>({name:l,value:f})),default:Object.keys(a)[0]});p||(console.error("No redis instance selected"),process.exit(1));let{stdout:d}=await r("kubectl",["get","pods","--no-headers","-o","custom-columns=:metadata.name"],{print:!1}),u=d.split(`
54
- `).find(l=>l.includes("redis"));u?.trim()||(console.error("No redis pod found"),process.exit(1));try{let{promise:l,resolve:f,reject:H}=Q(),z=We("kubectl",["exec","-it",u,"--","redis-cli","-h",p],{stdio:"inherit",shell:!0});z.on("exit",y=>{y!==0?H(new Error(`Process exited with code ${y}`)):f()}),z.on("error",y=>{console.error("Process error:",y),H(y)}),console.log("Connecting to Redis... Could take a few seconds \u23F1\uFE0F"),await l,process.exit(0)}catch(l){console.error("Failed to connect to Redis:",l),process.exit(1)}};var Fe=ee.join("/"),m=`--variationId=<yourVariationUuid> --cluster=<${Fe}>`,be={switchCluster:m,exposeService:`--service=<driver-ms> ${m}`,forwardDb:`${m} --local-port=<localPort>`,forwardService:`--service=<driver-ms> ${m} --port=<port> --local-port=<localPort>`,getIps:m,enableSimulator:m,rabbitCreds:m,updateExp:m,telepresenceWizard:`--service=<driver-ms> ${m} --local-port=<localPort>`,localDev:m,mirrord:`--service=<driver-ms> ${m}`,mirrordConfig:"--variationId=<yourVariationUuid>",dockerInit:"",openRedis:"--cluster=<${clusterOptions}"},Ve=e=>Object.keys(be).includes(e),{positionals:G,values:S,help:h}=J({strict:!0,binName:"autofleet",allowPositionals:!0,options:{cluster:{type:"string",short:"c",description:"The cluster name. One of dev1, e2eManager, expManager"},variationId:{type:"string",short:"i",description:"The variation id"},service:{type:"string",short:"s",description:"The service name"},port:{type:"string",short:"p",description:"The remote port to forward"},"local-port":{type:"string",short:"l",description:"The local port to forward to"},"prefer-pod":{type:"boolean",short:"r",default:!1,description:"Wether the mirrord command should run against the pod, rather than the deployment."}},commands:be});G.length||(console.log(h),process.exit(0));G.length>1&&c("Only one command is allowed",h);var[b]=G;if(!Ve(b))throw c(new Error(`Command ${b} does not exist`),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");var Le={switchCluster:["cluster"],exposeService:["cluster","variationId","service"],forwardDb:["cluster","variationId",{option:"local-port",defaultVal:"5432"}],forwardService:["cluster","variationId","service","port"],telepresenceWizard:["cluster","service"],mirrordConfig:["variationId"],mirrord:["cluster",{option:"variationId",defaultVal:b==="mirrord"?await le():""},"service"],dockerInit:[],openRedis:["cluster"]};await k(S,Le[b]??["cluster","variationId"]);var{cluster:E,variationId:w,service:C}=S;switch(b){case"mirrordConfig":await U(w);break;case"dockerInit":await j();break}if(!E)throw c(new Error("cluster required"),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");switch(b){case"telepresenceWizard":await P(S);break;case"switchCluster":await T(E,w);break;case"openRedis":await q(E);break}if(!w){throw c(new Error("variationId required"),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");process.exit(1)}var g;try{g=await re({clusterName:E,variationId:w})}catch(e){throw c(e),new Error("Typescript is not clever enough to understand that endWithError will exit the process")}switch(b){case"mirrord":await N(g,w,C);break;case"exposeService":await D(g,h,C);break;case"forwardDb":await A(S,g,w,h,C);break;case"forwardService":await M(S,g,h,C);break;case"getIps":await O(g);break;case"enableSimulator":await W(g,w);break;case"rabbitCreds":await F();break;case"updateExp":await V(g);break;case"localDev":await B(g,E,w);break}
80
+ elasticsearch_data:
81
+ `,j=async()=>{let e=ge.join(he.tmpdir(),"docker-compose.yml");we.writeFileSync(e,Me),await r("docker-compose",["-f",e,"up","-d"],{print:!1}),console.log("--------------------------------------------------------------------------------"),console.log(`Successfully started the services:
82
+ `),console.log("redis: localhost:6379 \u{1F680}"),console.log("postgres: localhost:5432, user: postgres, password: postgres \u{1F418}"),console.log("rabbitmq: localhost:5672 and http://localhost:15672, user: guest, password: guest \u{1F407}"),console.log("elasticsearch: localhost:9200 \u2753"),console.log("kibana: http://localhost:5601 \u2753"),process.exit(0)};import{spawn as We}from"node:child_process";var q=async e=>{ae(e)&&(console.error("Connecting to Redis is not supported for simulation clusters (need to be added)"),process.exit(1));let{project:o,name:t}=await v(e),i=se(e),{stdout:s}=await r("gcloud",["redis","instances","list","--region",i,"--project",o||t,"--format","json"],{print:!1}),n;try{n=JSON.parse(s)}catch(l){console.error("Failed to parse redis instances",{redisInstances:s,e:l}),process.exit(1)}let a=Object.fromEntries(n.map(l=>{let f=l.name.split("/");return[l.displayName||f?.at(-1)||l.name,l.host]})),p=await $({message:"which redis instance do you want to connect to?",choices:Object.entries(a).map(([l,f])=>({name:l,value:f})),default:Object.keys(a)[0]});p||(console.error("No redis instance selected"),process.exit(1));let{stdout:d}=await r("kubectl",["get","pods","--no-headers","-o","custom-columns=:metadata.name"],{print:!1}),u=d.split(`
83
+ `).find(l=>l.includes("redis"));u?.trim()||(console.error("No redis pod found"),process.exit(1));try{let{promise:l,resolve:f,reject:H}=Q(),z=We("kubectl",["exec","-it",u,"--","redis-cli","-h",p],{stdio:"inherit",shell:!0});z.on("exit",y=>{y!==0?H(new Error(`Process exited with code ${y}`)):f()}),z.on("error",y=>{console.error("Process error:",y),H(y)}),console.log("Connecting to Redis... Could take a few seconds \u23F1\uFE0F"),await l,process.exit(0)}catch(l){console.error("Failed to connect to Redis:",l),process.exit(1)}};var Fe=ee.join("/"),m=`--variationId=<yourVariationUuid> --cluster=<${Fe}>`,be={switchCluster:m,exposeService:`--service=<driver-ms> ${m}`,forwardDb:`${m} --local-port=<localPort>`,forwardService:`--service=<driver-ms> ${m} --port=<port> --local-port=<localPort>`,getIps:m,enableSimulator:m,rabbitCreds:m,updateExp:m,telepresenceWizard:`--service=<driver-ms> ${m} --local-port=<localPort>`,localDev:m,mirrord:`--service=<driver-ms> ${m}`,mirrordConfig:"--variationId=<yourVariationUuid>",dockerInit:"",openRedis:"--cluster=<${clusterOptions}"},Ve=e=>Object.keys(be).includes(e),{positionals:G,values:S,help:h}=J({strict:!0,binName:"autofleet",allowPositionals:!0,options:{cluster:{type:"string",short:"c",description:"The cluster name. One of dev1, e2eManager, expManager"},variationId:{type:"string",short:"i",description:"The variation id"},service:{type:"string",short:"s",description:"The service name"},port:{type:"string",short:"p",description:"The remote port to forward"},"local-port":{type:"string",short:"l",description:"The local port to forward to"},"prefer-pod":{type:"boolean",short:"r",default:!1,description:"Wether the mirrord command should run against the pod, rather than the deployment."}},commands:be});G.length||(console.log(h),process.exit(0));G.length>1&&c("Only one command is allowed",h);var[b]=G;if(!Ve(b))throw c(new Error(`Command ${b} does not exist`),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");var Le={switchCluster:["cluster"],exposeService:["cluster","variationId","service"],forwardDb:["cluster","variationId",{option:"local-port",defaultVal:"5432"}],forwardService:["cluster","variationId","service","port"],telepresenceWizard:["cluster","service"],mirrordConfig:["variationId"],mirrord:["cluster",{option:"variationId",defaultVal:b==="mirrord"?await le():""},"service"],dockerInit:[],openRedis:["cluster"]};await k(S,Le[b]??["cluster","variationId"]);var{cluster:E,variationId:w,service:_}=S;switch(b){case"mirrordConfig":await U(w);break;case"dockerInit":await j();break}if(!E)throw c(new Error("cluster required"),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");switch(b){case"telepresenceWizard":await P(S);break;case"switchCluster":await T(E,w);break;case"openRedis":await q(E);break}if(!w){throw c(new Error("variationId required"),h),new Error("Typescript is not clever enough to understand that endWithError will exit the process");process.exit(1)}var g;try{g=await re({clusterName:E,variationId:w})}catch(e){throw c(e),new Error("Typescript is not clever enough to understand that endWithError will exit the process")}switch(b){case"mirrord":await N(g,w,_);break;case"exposeService":await D(g,h,_);break;case"forwardDb":await A(S,g,w,h,_);break;case"forwardService":await O(S,g,h,_);break;case"getIps":await M(g);break;case"enableSimulator":await W(g,w);break;case"rabbitCreds":await F();break;case"updateExp":await V(g);break;case"localDev":await B(g,E,w);break}
55
84
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../bin/utils/mirrord.ts","../bin/utils/exitHandler.ts","../bin/commands/base/mirrord.ts","../bin/commands/base/switchCluster.ts","../bin/commands/base/telepresenceWizard.ts","../bin/commands/base/exposeService.ts","../bin/commands/base/forwardDb.ts","../bin/commands/base/forwardService.ts","../bin/commands/base/getIps.ts","../bin/commands/base/enableSimulator.ts","../bin/commands/base/rabbitCreds.ts","../bin/commands/base/updateExp.ts","../bin/commands/base/localDev.ts","../bin/utils/env.ts","../bin/commands/base/mirrordConfig.ts","../bin/commands/base/dockerInit.ts","../bin/commands/base/openRedis.ts","../bin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { getGitPath } from './git.js';\nimport { mkdir, writeFile, readFile } from 'node:fs/promises';\n\nexport const MIRRORD_FOLDER_NAME = '.mirrord';\n\nasync function getMirrodFolderPath({ makeDir = false } = {}) {\n const repoPath = await getGitPath();\n const mirrordPath = join(repoPath, MIRRORD_FOLDER_NAME);\n if (makeDir) {\n await mkdir(mirrordPath, { recursive: true });\n }\n return join(mirrordPath, 'mirrord.json');\n}\n\nexport async function writeMirrordFile(variationId?: string) {\n const mirrordPath = await getMirrodFolderPath({ makeDir: true });\n const mirrordConfigData = {\n feature: {\n network: {\n incoming: {\n mode: 'steal',\n http_filter: {\n path_filter: '^(?!/alive)',\n },\n },\n outgoing: true,\n },\n fs: 'read',\n env: true,\n },\n target: {\n namespace: variationId || randomUUID(),\n },\n };\n await writeFile(mirrordPath, JSON.stringify(mirrordConfigData, null, 2));\n\n return { mirrordConfigData, mirrordPath };\n}\n\nexport async function getVariationIdFromMirrodConfig() {\n try {\n const mirrordPath = await getMirrodFolderPath();\n const mirrordConfigDataString = await readFile(mirrordPath, { encoding: 'utf-8' });\n const mirrordConfigData = JSON.parse(mirrordConfigDataString || '{}') as { target?: { namespace?: string } };\n return mirrordConfigData?.target?.namespace ?? '';\n } catch {\n return '';\n }\n}\n","/* eslint-disable @typescript-eslint/no-misused-promises */\n\nexport function registerProcessForCleanup(onExit: (e?: unknown) => void | PromiseLike<void>) {\n process.once('exit', onExit);\n process.once('SIGTERM', onExit);\n process.once('SIGINT', onExit);\n}\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\nimport { registerProcessForCleanup } from '../../utils/exitHandler.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var executedExitHooks: boolean;\n}\n\nfunction trimProbeString(str: string): string {\n str &&= str.trim();\n if (!str) {\n return str;\n }\n if (str.startsWith('\\'') && str.endsWith('\\'')) {\n str = str.slice(1, -1);\n }\n return str;\n}\n\nconst LIVENESS_PROBE = 'livenessProbe';\nconst READINESS_PROBE = 'readinessProbe';\nconst WORKER_PATH = (leaf: string) => `jsonpath='{.spec.template.spec.containers[?(@.name==\"worker\")].${leaf}}'`;\nconst SET_PROBE_VALUES = (...probeAndValues: [string, string][]) => `{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"worker\",${probeAndValues.map(([probe, value]) => `\"${probe}\": ${value}`).join(',')}}]}}}}`;\n\nexport default async (prefix: string, variationId: string, service?: string) => {\n console.log('Will now disable health check to allow debugging.');\n let [{ stdout: livenessProbe }, { stdout: readinessProbe }] = await Promise.all([\n await asyncSpawn('kubectl', ['get', `deployment/${service}`, prefix, '-o', WORKER_PATH(LIVENESS_PROBE)], { print: false }),\n await asyncSpawn('kubectl', ['get', `deployment/${service}`, prefix, '-o', WORKER_PATH(READINESS_PROBE)], { print: false }),\n ]);\n livenessProbe &&= trimProbeString(livenessProbe);\n readinessProbe &&= trimProbeString(readinessProbe);\n if (livenessProbe || readinessProbe) {\n await asyncSpawn('kubectl', ['patch', `deployment/${service}`, prefix, '--patch', SET_PROBE_VALUES([LIVENESS_PROBE, 'null'], [READINESS_PROBE, 'null'])], { print: false });\n console.log('Health check disabled, will now start mirrord and run \"npm run dev\". Make sure to attach a debugger!');\n }\n const abortController = new AbortController();\n registerProcessForCleanup(async () => {\n if (globalThis.executedExitHooks) {\n return;\n }\n globalThis.executedExitHooks = true;\n abortController.abort();\n if (livenessProbe || readinessProbe) {\n console.log('Re-enabling health check.');\n await asyncSpawn('kubectl', ['patch', `deployment/${service}`, prefix, '--patch', `'${SET_PROBE_VALUES([LIVENESS_PROBE, livenessProbe], [READINESS_PROBE, readinessProbe])}'`], { print: false, shell: true });\n console.log('health check enabled.');\n }\n process.exit(0);\n });\n try {\n await asyncSpawn('mirrord', ['exec', '-t', `deployment/${service}`, '-n', variationId, '--steal', 'npm', 'run', 'dev'], { signal: abortController.signal });\n } catch (error) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 'ABORT_ERR') {\n return;\n }\n endWithError(error as Error);\n }\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { connectToCluster, getCurrentNamespace } from '../../utils/index.js';\nimport { fillMissingRequiredValues } from '../../utils/inquirer.js';\n\nexport default async (cluster: string, variationId?: string) => {\n await connectToCluster(cluster);\n\n if (cluster === 'expManager' || cluster === 'dev1') {\n const { variationId: namespace } = await fillMissingRequiredValues({ variationId }, ['variationId']);\n if (namespace !== '') {\n if (await getCurrentNamespace() === namespace) {\n console.log(`Already connected to simulation with uuid: ${namespace}, skipping namespace switch...`);\n process.exit(0);\n }\n await asyncSpawn('kubectl', ['config', 'set-context', '--current', `--namespace=${namespace}`], { print: false });\n console.log(`Switched to simulation with uuid: ${namespace} successfully`);\n }\n }\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { getVariationId, getLocalPort, safeSelect } from '../../utils/inquirer.js';\nimport { connectToCluster, endWithError } from '../../utils/index.js';\nimport type { Values } from '../../index.js';\n\nasync function ensureTelepresenceInstalled() {\n try {\n await asyncSpawn('telepresence', ['version'], { print: false });\n } catch {\n endWithError('Telepresence is not installed. Please install it from:\\nhttps://www.telepresence.io/docs/latest/quick-start/');\n }\n}\n\nfunction leaveOrConnect() {\n return safeSelect({\n message: 'Do you want to leave the connection or create a new one?',\n choices: [\n { name: 'Leave the current connection', value: 'leave' },\n { name: 'Create a new connection', value: 'connect' },\n ] as const,\n default: 'connect',\n });\n}\n\nexport default async function telepresenceWizard(values: Values): Promise<void> {\n await ensureTelepresenceInstalled();\n\n const { cluster = '', service = '' } = values; // Values should be defined by now, thanks to inquirer. Default to hint to TS we always have values.\n await connectToCluster(cluster);\n\n const action = await leaveOrConnect();\n if (!['leave', 'connect'].includes(action!)) {\n endWithError('Invalid action, how did you get here? 🤔');\n }\n if (action === 'leave') {\n await asyncSpawn('telepresence', ['leave', service]);\n console.log('Disconnected! 👋');\n return;\n }\n const namespace = values.variationId || await getVariationId();\n const localPort = (values['local-port'] && Number.parseInt(values['local-port'], 10)) || Number.parseInt((await getLocalPort()) || '', 10);\n await asyncSpawn('telepresence', ['connect', `--namespace=${namespace}`]);\n await asyncSpawn('telepresence', ['intercept', service, '--port', localPort.toString(), '--env-file=./.env']);\n console.log('Everything is set up! 🚀');\n console.log(`You can now access the service at localhost:${localPort}`);\n console.log('You can only have one connection at a time. If you want to connect to a different service, you need to leave the current connection first.');\n process.exit(0);\n}\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\nexport default async (prefix: string, help: string, service?: string) => {\n if (!service) {\n endWithError(new Error('service is required for exposeService'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n }\n await asyncSpawn('kubectl', ['patch', 'svc', prefix, service, '-p', '{\"spec\": {\"type\": \"LoadBalancer\"}}']);\n console.log(`exposed ${service} successfully. the service is now creating an internal load balancer ip to use with vpn`);\n process.exit(0);\n};\n","import { setTimeout } from 'node:timers/promises';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\ninterface Values {\n 'local-port'?: string;\n}\n\nexport default async (values: Values, prefix: string, variationId: string, help: string, service?: string) => {\n const localPort = Number.parseInt(values['local-port'] ?? '5432', 10);\n if (Number.isNaN(localPort)) {\n endWithError(new Error('if defined, local-port must be a number'), help);\n }\n const DB_PASSWORD = `afpass_${variationId}`;\n const USER_NAME = 'postgres';\n const variationUnderScore = variationId.replaceAll('-', '_');\n const DB_NAME = service ? `${service.replaceAll('-', '_') || ''}_${variationUnderScore}` : 'postgres';\n\n const postgressPath = `postgres://${USER_NAME}:${DB_PASSWORD}@localhost:${localPort}/${DB_NAME}?&nickname=var_${variationId}`;\n console.log(`Forwarding db to local port ${localPort}.\\naccess the DB at ${postgressPath}\\nPress ctrl+c to stop.`);\n\n const dbEnvs = ` DB_USERNAME=${USER_NAME}\n DB_PASSWORD=${DB_PASSWORD}\n DB_NAME=${service ? DB_NAME : `<service_name>_${variationUnderScore}`}`;\n console.log('Generated database environment for local development:\\n', dbEnvs);\n\n setTimeout(1500).then(() => asyncSpawn('open', [postgressPath], { print: false })).catch(() => null);\n await asyncSpawn('kubectl', [prefix, 'port-forward', `statefulset/p${variationId}-postgresql`, `${localPort}:5432`], { print: false });\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\ninterface Values {\n port?: string;\n 'local-port'?: string;\n}\n\nexport default async (values: Values, prefix: string, help: string, service?: string) => {\n const port = Number.parseInt(values.port ?? '8080', 10);\n const localPort = Number.parseInt(values['local-port'] ?? '', 10) || port;\n if (!service) {\n endWithError(new Error('service is required for forwardService'), help);\n }\n if (!port || Number.isNaN(port)) {\n endWithError(new Error('port is required and must be a numbers'), help);\n }\n if (localPort && Number.isNaN(localPort)) {\n endWithError(new Error('local-port must be a number'), help);\n }\n let { stdout: podName } = await asyncSpawn('kubectl', ['get', 'pods', prefix, '-l', `service=${service}`, '-o', 'jsonpath=\"{.items[0].metadata.name}\"'], { print: false });\n podName &&= podName.trim();\n if (!podName) {\n endWithError(new Error(`No pods found for service ${service}`));\n }\n if (podName.startsWith('\"') && podName.endsWith('\"')) {\n podName = podName.slice(1, -1);\n }\n console.log(`Found pod ${podName}, serving locally on port ${localPort} from remote port ${port}.\\nPress ctrl+c to stop.`);\n await asyncSpawn('kubectl', ['port-forward', prefix, podName, `${localPort}:${port}`], { print: false });\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { parseIps } from '../../utils/index.js';\n\nexport default async (prefix: string) => {\n const { stdout } = await asyncSpawn('kubectl', [prefix, 'get', 'services'], { print: false });\n const ips = parseIps(stdout);\n ips.forEach(ip => console.log(ip));\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\n\nexport default async (prefix: string, variationId: string) => {\n const SIMULATION_CLUSTER_FRONT = 'simulation-cluster-front';\n await asyncSpawn('kubectl', ['annotate', prefix, 'service', SIMULATION_CLUSTER_FRONT, 'cloud.google.com/load-balancer-type-']);\n await asyncSpawn('kubectl', ['patch', 'svc', prefix, SIMULATION_CLUSTER_FRONT, '-p', '{\"spec\": {\"type\": \"LoadBalancer\"}}']);\n await asyncSpawn('kubectl', ['create', prefix, 'rolebinding', 'admin', '--clusterrole=cluster-admin', `--serviceaccount=${variationId}:default`]);\n console.log(`Successfully exposed ${SIMULATION_CLUSTER_FRONT} and added role binding to dispatch simulations`);\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\n\nexport default async () => {\n const getArgs = (dataKey: string) => ['get', 'secret', 'rabbitmq-default-user', '-o', `jsonpath=\"{.data.${dataKey}}\"`];\n const [{ stdout: username }, { stdout: password }] = await Promise.all([\n asyncSpawn('kubectl', getArgs('username'), { print: false }),\n asyncSpawn('kubectl', getArgs('password'), { print: false }),\n ]);\n console.log(`username: ${Buffer.from(username, 'base64').toString('ascii')}`);\n console.log(`password: ${Buffer.from(password, 'base64').toString('ascii')}`);\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { basename } from 'node:path';\nimport { cwd } from 'node:process';\nimport { getCurrentBranch } from '../../utils/git.js';\n\nexport default async (prefix: string) => {\n const dir = basename(cwd());\n const [branchName, archResult] = await Promise.all([getCurrentBranch(), asyncSpawn('uname', ['-m'], { print: false })]);\n const arch = archResult.stdout.trim();\n const dateSuffix = `${new Date().getHours().toString().padStart(2, '0')}-${new Date().getMinutes().toString().padStart(2, '0')}-${new Date().getSeconds().toString().padStart(2, '0')}`;\n const imageName = `gcr.io/autofleetprod/${dir}:${branchName}-${dateSuffix}`;\n console.log(`Building and pushing image ${imageName}`);\n const platformFlag = arch === 'x86_64' ? [] : ['--platform', 'linux/amd64'];\n await asyncSpawn('docker', ['build', '.', ...platformFlag, '-t', imageName, '--build-arg', `NPM_TOKEN=${process.env.NPM_TOKEN}`]);\n await asyncSpawn('docker', ['push', imageName]);\n const { stdout: podDescription } = await asyncSpawn('kubectl', ['describe', 'pod', prefix, '-l', `service=${dir}`], { print: false });\n if (podDescription.includes('Init Containers:')) {\n await asyncSpawn('kubectl', ['patch', `deployment/${dir}`, prefix, '--patch', `{\"spec\": {\"template\": {\"spec\": {\"initContainers\": [{\"name\": \"init\",\"image\": \"${imageName}\"}]}}}}`]);\n }\n await asyncSpawn('kubectl', ['set', 'image', `deployment/${dir}`, `worker=${imageName}`, prefix]);\n await asyncSpawn('kubectl', ['rollout', 'status', 'deployments', dir, prefix]);\n process.exit(0);\n};\n","import { basename } from 'node:path';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { getGitPath } from '../../utils/git.js';\nimport { endWithError } from '../../utils/index.js';\nimport { setEnvValue } from '../../utils/env.js';\n\nexport default async (prefix: string, cluster: string, variationId: string) => {\n const LOCAL_ENV_NAME = 'LOCAL_ENV_NAME';\n const API_GATEWAY_MS = 'api-gateway-ms';\n const CONTROL_CENTER_MS = 'control-center-ms';\n const envNameToUse = cluster === 'staging' ? 'staging' : `simulator-${variationId}`;\n\n const repoPath = await getGitPath();\n if (basename(repoPath) !== 'control-center') {\n endWithError(new Error('The `localDev` command must be run from the control-center repository'));\n }\n const { stdout: apiGatewayMsIP } = await asyncSpawn('kubectl', ['get', 'ingress', `${API_GATEWAY_MS}-ingress`, prefix, '-o', 'jsonpath=\"{.status.loadBalancer.ingress[0].ip}\"'], { print: false });\n if (!apiGatewayMsIP) {\n endWithError(new Error(`The IP of the Load balancer for ${API_GATEWAY_MS} was not found`));\n }\n const changedIP = await setEnvValue(repoPath, 'API_GATEWAY_MS_SERVICE_HOST', apiGatewayMsIP.replace(/\"/g, ''));\n const changedEnvName = await setEnvValue(repoPath, LOCAL_ENV_NAME, envNameToUse);\n const msg = `${\n changedIP ? `Updated .env file to use ${API_GATEWAY_MS} IP (${apiGatewayMsIP}).\\n` : ''\n }${\n changedEnvName ? `Updated .env file ${LOCAL_ENV_NAME} to ${envNameToUse} (used for firebase setup).\\n` : ''\n }Port-forwarding of ${CONTROL_CENTER_MS} will now start to port 8085.\\nPress ctrl+c to stop.`;\n console.log(msg);\n await asyncSpawn('kubectl', ['port-forward', prefix, `svc/${CONTROL_CENTER_MS}`, '8085:80'], { print: false });\n process.exit(0);\n};\n","import { EOL } from 'node:os';\nimport { resolve } from 'node:path';\nimport { readFile, writeFile } from 'node:fs/promises';\n\nexport async function setEnvValue(repoRoot: string, key: string, value: string): Promise<boolean> {\n const filePath = resolve(repoRoot, '.env');\n const envFileContent = await readFile(filePath, 'utf8');\n const envVars = envFileContent.split(EOL);\n\n // (?<!#\\\\s*) Negative lookbehind to avoid matching comments (lines that starts with #).\n // There is a double slash in the RegExp constructor to escape it.\n // (?==) Positive lookahead to check if there is an equal sign right after the key.\n // This is to prevent matching keys prefixed with the key of the env var to update.\n const regexString = `(?<!#\\\\s*)${key}(?==)`;\n const matchingLine = envVars.find((line: string) => line.match(regexString));\n\n if (matchingLine?.split('=').at(-1) === value) {\n return false;\n }\n\n const target = matchingLine ? envVars.indexOf(matchingLine) : -1;\n\n if (target !== -1) {\n envVars.splice(target, 1, `${key}=${value}`);\n } else {\n envVars.push(`${key}=${value}`);\n }\n\n await writeFile(filePath, envVars.join(EOL));\n return true;\n}\n","import { resolve } from 'node:path';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { isPathIgnored } from '../../utils/git.js';\nimport { writeMirrordFile, MIRRORD_FOLDER_NAME } from '../../utils/mirrord.js';\n\nasync function addToGitIgnore(mirrordPath: string) {\n const isIgnored = await isPathIgnored(MIRRORD_FOLDER_NAME);\n if (isIgnored) {\n return;\n }\n const gitIgnoreFile = resolve(mirrordPath, '..', '..', '.gitignore');\n const gitIgnoreFileContent = await readFile(gitIgnoreFile, 'utf8');\n const gitIgnoreFileContentLines = gitIgnoreFileContent.split('\\n').filter(Boolean);\n gitIgnoreFileContentLines.push(MIRRORD_FOLDER_NAME);\n await writeFile(gitIgnoreFile, `${gitIgnoreFileContentLines.join('\\n')}\\n`);\n}\n\nexport default async (variationId?: string) => {\n const { mirrordConfigData, mirrordPath } = await writeMirrordFile(variationId);\n await addToGitIgnore(mirrordPath);\n console.log('Wrote the default mirrord config for the requested variation ID', { mirrordConfigData });\n process.exit(0);\n};\n","import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\n\nconst dockerComposeFile = `\nservices:\n redis:\n image: redis:6\n ports:\n - \"6379:6379\"\n volumes:\n - redis_data:/data\n command: redis-server --appendonly yes\n\n rabbitmq:\n image: rabbitmq:3.12.13-management\n ports:\n - \"5672:5672\" # AMQP protocol port\n - \"15672:15672\" # Management UI port\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n environment:\n - RABBITMQ_DEFAULT_USER=guest\n - RABBITMQ_DEFAULT_PASS=guest\n\n postgres:\n image: postgis/postgis:14-3.3\n platform: linux/amd64\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n environment:\n - POSTGRES_DB=postgres\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=postgres\n\nvolumes:\n redis_data:\n rabbitmq_data:\n postgres_data:\n`;\n\nexport default async () => {\n const dockerComposePath = path.join(os.tmpdir(), 'docker-compose.yml');\n fs.writeFileSync(dockerComposePath, dockerComposeFile);\n await asyncSpawn('docker-compose', ['-f', dockerComposePath, 'up', '-d'], { print: false });\n console.log('--------------------------------------------------------------------------------');\n console.log('Successfully started the services:\\n');\n console.log('redis: localhost:6379 🚀');\n console.log('postgres: localhost:5432, user: postgres, password: postgres 🐘');\n console.log('rabbitmq: localhost:5672, user: guest, password: guest 🐇');\n process.exit(0);\n};\n","import { spawn } from 'node:child_process';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { connectToCluster, getRedisRegion, isSimulationCluster } from '../../utils/index.js';\nimport { safeSelect } from '../../utils/inquirer.js';\nimport { createDeferredPromise } from '../../utils/promise.js';\n\ninterface RedisInstance {\n displayName?: string;\n host: string;\n name: string;\n}\n\nexport default async (clusterName: string) => {\n if (isSimulationCluster(clusterName)) {\n console.error('Connecting to Redis is not supported for simulation clusters (need to be added)');\n process.exit(1);\n }\n\n const {\n project,\n name,\n } = await connectToCluster(clusterName);\n const redisRegion = getRedisRegion(clusterName);\n const { stdout: redisInstances } = await asyncSpawn('gcloud', ['redis', 'instances', 'list', '--region', redisRegion, '--project', project || name, '--format', 'json'], { print: false });\n let redisInstancesJson;\n try {\n redisInstancesJson = JSON.parse(redisInstances) as RedisInstance[];\n } catch (e) {\n console.error('Failed to parse redis instances', { redisInstances, e });\n process.exit(1);\n }\n\n const redisNameToIpMap = Object.fromEntries(redisInstancesJson.map((instance: RedisInstance) => {\n const redisPath = instance.name.split('/');\n return [instance.displayName || redisPath?.at(-1) || instance.name, instance.host];\n }));\n\n const redisIp = await safeSelect({\n message: 'which redis instance do you want to connect to?',\n choices: Object.entries(redisNameToIpMap).map(([name, ip]) => ({ name, value: ip })),\n default: Object.keys(redisNameToIpMap)[0],\n });\n\n if (!redisIp) {\n console.error('No redis instance selected');\n process.exit(1);\n }\n\n const { stdout: allPodsName } = await asyncSpawn('kubectl', ['get', 'pods', '--no-headers', '-o', 'custom-columns=:metadata.name'], { print: false });\n const redisPodName = allPodsName.split('\\n').find(podName => podName.includes('redis'));\n\n if (!redisPodName?.trim()) {\n console.error('No redis pod found');\n process.exit(1);\n }\n\n try {\n const { promise, resolve, reject } = createDeferredPromise<void>();\n const shell = spawn('kubectl', [\n 'exec',\n '-it',\n redisPodName,\n '--',\n 'redis-cli',\n '-h',\n redisIp,\n ], {\n stdio: 'inherit',\n shell: true,\n });\n shell.on('exit', (code) => {\n if (code !== 0) {\n reject(new Error(`Process exited with code ${code}`));\n } else {\n resolve();\n }\n });\n shell.on('error', (error) => {\n console.error('Process error:', error);\n reject(error);\n });\n\n console.log('Connecting to Redis... Could take a few seconds ⏱️');\n\n await promise;\n\n process.exit(0);\n } catch (error) {\n console.error('Failed to connect to Redis:', error);\n process.exit(1);\n }\n};\n","#!/usr/bin/env node\nimport parseArgs from './utils/parser.js';\nimport {\n SUPPORTED_CLUSTERS,\n connectAndGetPrefix, endWithError,\n} from './utils/index.js';\nimport { fillMissingRequiredValues } from './utils/inquirer.js';\nimport { getVariationIdFromMirrodConfig } from './utils/mirrord.js';\nimport {\n mirrord,\n switchCluster,\n telepresenceWizard,\n enableSimulator,\n exposeService,\n forwardDb,\n forwardService,\n getIps,\n localDev,\n rabbitCreds,\n updateExp,\n mirrordConfig,\n dockerInit,\n openRedis,\n} from './commands/index.js';\n\nconst clusterOptions = SUPPORTED_CLUSTERS.join('/');\nconst variationAndCluster = `--variationId=<yourVariationUuid> --cluster=<${clusterOptions}>`;\n\nconst COMMANDS = {\n switchCluster: variationAndCluster,\n exposeService: `--service=<driver-ms> ${variationAndCluster}`,\n forwardDb: `${variationAndCluster} --local-port=<localPort>`,\n forwardService: `--service=<driver-ms> ${variationAndCluster} --port=<port> --local-port=<localPort>`,\n getIps: variationAndCluster,\n enableSimulator: variationAndCluster,\n rabbitCreds: variationAndCluster,\n updateExp: variationAndCluster,\n telepresenceWizard: `--service=<driver-ms> ${variationAndCluster} --local-port=<localPort>`,\n localDev: variationAndCluster,\n mirrord: `--service=<driver-ms> ${variationAndCluster}`,\n mirrordConfig: '--variationId=<yourVariationUuid>',\n dockerInit: '',\n openRedis: '--cluster=<${clusterOptions}',\n};\ntype Command = keyof typeof COMMANDS;\nconst isCommand = (c: string): c is Command => Object.keys(COMMANDS).includes(c);\n\nconst { positionals, values, help } = parseArgs({\n strict: true,\n binName: 'autofleet',\n allowPositionals: true,\n options: {\n cluster: {\n type: 'string',\n short: 'c',\n description: 'The cluster name. One of dev1, e2eManager, expManager',\n },\n variationId: {\n type: 'string',\n short: 'i',\n description: 'The variation id',\n },\n service: {\n type: 'string',\n short: 's',\n description: 'The service name',\n },\n port: {\n type: 'string',\n short: 'p',\n description: 'The remote port to forward',\n },\n 'local-port': {\n type: 'string',\n short: 'l',\n description: 'The local port to forward to',\n },\n 'prefer-pod': {\n type: 'boolean',\n short: 'r',\n default: false,\n description: 'Wether the mirrord command should run against the pod, rather than the deployment.',\n },\n },\n commands: COMMANDS,\n});\n\nexport type Values = typeof values;\ntype ValueWithDefault<T = keyof Values> = T | { option: T; defaultVal: string };\n\nif (!positionals.length) {\n console.log(help);\n process.exit(0);\n}\n\nif (positionals.length > 1) {\n endWithError('Only one command is allowed', help);\n}\n\nconst [command] = positionals;\nif (!isCommand(command)) {\n endWithError(new Error(`Command ${command} does not exist`), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nconst COMMAND_REQUIRED_VALUES_MAP: Partial<Record<Command, ValueWithDefault[]>> = {\n switchCluster: ['cluster'],\n exposeService: ['cluster', 'variationId', 'service'],\n forwardDb: ['cluster', 'variationId', { option: 'local-port', defaultVal: '5432' }],\n forwardService: ['cluster', 'variationId', 'service', 'port'],\n telepresenceWizard: ['cluster', 'service'],\n mirrordConfig: ['variationId'],\n mirrord: ['cluster', { option: 'variationId', defaultVal: command === 'mirrord' ? await getVariationIdFromMirrodConfig() : '' }, 'service'],\n dockerInit: [],\n openRedis: ['cluster'],\n};\n\nawait fillMissingRequiredValues(\n values,\n COMMAND_REQUIRED_VALUES_MAP[command] ?? ['cluster', 'variationId'],\n);\nconst { cluster, variationId, service } = values;\n\nswitch (command) {\ncase 'mirrordConfig':\n await mirrordConfig(variationId);\n break;\ncase 'dockerInit':\n await dockerInit();\n break;\n}\n\nif (!cluster) {\n endWithError(new Error('cluster required'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nswitch (command) {\ncase 'telepresenceWizard':\n await telepresenceWizard(values);\n break;\ncase 'switchCluster':\n await switchCluster(cluster, variationId);\n break;\ncase 'openRedis':\n await openRedis(cluster);\n break;\n}\n\nif (!variationId) {\n endWithError(new Error('variationId required'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n process.exit(1);\n}\nlet prefix: string;\ntry {\n prefix = await connectAndGetPrefix({ clusterName: cluster, variationId });\n} catch (error) {\n endWithError(error as Error);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nswitch (command) {\ncase 'mirrord':\n await mirrord(prefix, variationId, service);\n break;\ncase 'exposeService':\n await exposeService(prefix, help, service);\n break;\ncase 'forwardDb':\n await forwardDb(values, prefix, variationId, help, service);\n break;\ncase 'forwardService':\n await forwardService(values, prefix, help, service);\n break;\ncase 'getIps':\n await getIps(prefix);\n break;\ncase 'enableSimulator':\n await enableSimulator(prefix, variationId);\n break;\ncase 'rabbitCreds':\n await rabbitCreds();\n break;\ncase 'updateExp':\n await updateExp(prefix);\n break;\ncase 'localDev':\n await localDev(prefix, cluster, variationId);\n break;\n}\n"],"mappings":"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","names":["join","randomUUID","mkdir","writeFile","readFile","MIRRORD_FOLDER_NAME","getMirrodFolderPath","makeDir","repoPath","getGitPath","mirrordPath","join","writeMirrordFile","variationId","mirrordConfigData","randomUUID","getVariationIdFromMirrodConfig","mirrordConfigDataString","registerProcessForCleanup","onExit","trimProbeString","str","LIVENESS_PROBE","READINESS_PROBE","WORKER_PATH","leaf","SET_PROBE_VALUES","probeAndValues","probe","value","mirrord_default","prefix","variationId","service","livenessProbe","readinessProbe","asyncSpawn_default","abortController","registerProcessForCleanup","error","endWithError","switchCluster_default","cluster","variationId","connectToCluster","namespace","fillMissingRequiredValues","getCurrentNamespace","asyncSpawn_default","ensureTelepresenceInstalled","asyncSpawn_default","endWithError","leaveOrConnect","safeSelect","telepresenceWizard","values","cluster","service","connectToCluster","action","namespace","getVariationId","localPort","getLocalPort","exposeService_default","prefix","help","service","endWithError","asyncSpawn_default","setTimeout","forwardDb_default","values","prefix","variationId","help","service","localPort","endWithError","DB_PASSWORD","USER_NAME","variationUnderScore","DB_NAME","postgressPath","dbEnvs","setTimeout","asyncSpawn_default","forwardService_default","values","prefix","help","service","port","localPort","endWithError","podName","asyncSpawn_default","getIps_default","prefix","stdout","asyncSpawn_default","parseIps","ip","enableSimulator_default","prefix","variationId","SIMULATION_CLUSTER_FRONT","asyncSpawn_default","rabbitCreds_default","getArgs","dataKey","username","password","asyncSpawn_default","basename","cwd","updateExp_default","prefix","dir","basename","cwd","branchName","archResult","getCurrentBranch","asyncSpawn_default","arch","dateSuffix","imageName","podDescription","basename","EOL","resolve","readFile","writeFile","setEnvValue","repoRoot","key","value","filePath","envVars","regexString","matchingLine","line","target","localDev_default","prefix","cluster","variationId","LOCAL_ENV_NAME","API_GATEWAY_MS","CONTROL_CENTER_MS","envNameToUse","repoPath","getGitPath","basename","endWithError","apiGatewayMsIP","asyncSpawn_default","changedIP","setEnvValue","changedEnvName","msg","resolve","readFile","writeFile","addToGitIgnore","mirrordPath","isPathIgnored","MIRRORD_FOLDER_NAME","gitIgnoreFile","resolve","gitIgnoreFileContentLines","readFile","writeFile","mirrordConfig_default","variationId","mirrordConfigData","writeMirrordFile","path","fs","os","dockerComposeFile","dockerInit_default","dockerComposePath","asyncSpawn_default","spawn","openRedis_default","clusterName","isSimulationCluster","project","name","connectToCluster","redisRegion","getRedisRegion","redisInstances","asyncSpawn_default","redisInstancesJson","e","redisNameToIpMap","instance","redisPath","redisIp","safeSelect","ip","allPodsName","redisPodName","podName","promise","resolve","reject","createDeferredPromise","shell","spawn","code","error","clusterOptions","SUPPORTED_CLUSTERS","variationAndCluster","COMMANDS","isCommand","c","positionals","values","help","parseArgs","endWithError","command","COMMAND_REQUIRED_VALUES_MAP","getVariationIdFromMirrodConfig","fillMissingRequiredValues","cluster","variationId","service","mirrordConfig_default","dockerInit_default","telepresenceWizard","switchCluster_default","openRedis_default","prefix","connectAndGetPrefix","error","mirrord_default","exposeService_default","forwardDb_default","forwardService_default","getIps_default","enableSimulator_default","rabbitCreds_default","updateExp_default","localDev_default"]}
1
+ {"version":3,"sources":["../bin/utils/mirrord.ts","../bin/utils/exitHandler.ts","../bin/commands/base/mirrord.ts","../bin/commands/base/switchCluster.ts","../bin/commands/base/telepresenceWizard.ts","../bin/commands/base/exposeService.ts","../bin/commands/base/forwardDb.ts","../bin/commands/base/forwardService.ts","../bin/commands/base/getIps.ts","../bin/commands/base/enableSimulator.ts","../bin/commands/base/rabbitCreds.ts","../bin/commands/base/updateExp.ts","../bin/commands/base/localDev.ts","../bin/utils/env.ts","../bin/commands/base/mirrordConfig.ts","../bin/commands/base/dockerInit.ts","../bin/commands/base/openRedis.ts","../bin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { getGitPath } from './git.js';\nimport { mkdir, writeFile, readFile } from 'node:fs/promises';\n\nexport const MIRRORD_FOLDER_NAME = '.mirrord';\n\nasync function getMirrodFolderPath({ makeDir = false } = {}) {\n const repoPath = await getGitPath();\n const mirrordPath = join(repoPath, MIRRORD_FOLDER_NAME);\n if (makeDir) {\n await mkdir(mirrordPath, { recursive: true });\n }\n return join(mirrordPath, 'mirrord.json');\n}\n\nexport async function writeMirrordFile(variationId?: string) {\n const mirrordPath = await getMirrodFolderPath({ makeDir: true });\n const mirrordConfigData = {\n feature: {\n network: {\n incoming: {\n mode: 'steal',\n http_filter: {\n path_filter: '^(?!/alive)',\n },\n },\n outgoing: true,\n },\n fs: 'read',\n env: true,\n },\n target: {\n namespace: variationId || randomUUID(),\n },\n };\n await writeFile(mirrordPath, JSON.stringify(mirrordConfigData, null, 2));\n\n return { mirrordConfigData, mirrordPath };\n}\n\nexport async function getVariationIdFromMirrodConfig() {\n try {\n const mirrordPath = await getMirrodFolderPath();\n const mirrordConfigDataString = await readFile(mirrordPath, { encoding: 'utf-8' });\n const mirrordConfigData = JSON.parse(mirrordConfigDataString || '{}') as { target?: { namespace?: string } };\n return mirrordConfigData?.target?.namespace ?? '';\n } catch {\n return '';\n }\n}\n","/* eslint-disable @typescript-eslint/no-misused-promises */\n\nexport function registerProcessForCleanup(onExit: (e?: unknown) => void | PromiseLike<void>) {\n process.once('exit', onExit);\n process.once('SIGTERM', onExit);\n process.once('SIGINT', onExit);\n}\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\nimport { registerProcessForCleanup } from '../../utils/exitHandler.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var executedExitHooks: boolean;\n}\n\nfunction trimProbeString(str: string): string {\n str &&= str.trim();\n if (!str) {\n return str;\n }\n if (str.startsWith('\\'') && str.endsWith('\\'')) {\n str = str.slice(1, -1);\n }\n return str;\n}\n\nconst LIVENESS_PROBE = 'livenessProbe';\nconst READINESS_PROBE = 'readinessProbe';\nconst WORKER_PATH = (leaf: string) => `jsonpath='{.spec.template.spec.containers[?(@.name==\"worker\")].${leaf}}'`;\nconst SET_PROBE_VALUES = (...probeAndValues: [string, string][]) => `{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"worker\",${probeAndValues.map(([probe, value]) => `\"${probe}\": ${value}`).join(',')}}]}}}}`;\n\nexport default async (prefix: string, variationId: string, service?: string) => {\n console.log('Will now disable health check to allow debugging.');\n let [{ stdout: livenessProbe }, { stdout: readinessProbe }] = await Promise.all([\n await asyncSpawn('kubectl', ['get', `deployment/${service}`, prefix, '-o', WORKER_PATH(LIVENESS_PROBE)], { print: false }),\n await asyncSpawn('kubectl', ['get', `deployment/${service}`, prefix, '-o', WORKER_PATH(READINESS_PROBE)], { print: false }),\n ]);\n livenessProbe &&= trimProbeString(livenessProbe);\n readinessProbe &&= trimProbeString(readinessProbe);\n if (livenessProbe || readinessProbe) {\n await asyncSpawn('kubectl', ['patch', `deployment/${service}`, prefix, '--patch', SET_PROBE_VALUES([LIVENESS_PROBE, 'null'], [READINESS_PROBE, 'null'])], { print: false });\n console.log('Health check disabled, will now start mirrord and run \"npm run dev\". Make sure to attach a debugger!');\n }\n const abortController = new AbortController();\n registerProcessForCleanup(async () => {\n if (globalThis.executedExitHooks) {\n return;\n }\n globalThis.executedExitHooks = true;\n abortController.abort();\n if (livenessProbe || readinessProbe) {\n console.log('Re-enabling health check.');\n await asyncSpawn('kubectl', ['patch', `deployment/${service}`, prefix, '--patch', `'${SET_PROBE_VALUES([LIVENESS_PROBE, livenessProbe], [READINESS_PROBE, readinessProbe])}'`], { print: false, shell: true });\n console.log('health check enabled.');\n }\n process.exit(0);\n });\n try {\n await asyncSpawn('mirrord', ['exec', '-t', `deployment/${service}`, '-n', variationId, '--steal', 'npm', 'run', 'dev'], { signal: abortController.signal });\n } catch (error) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 'ABORT_ERR') {\n return;\n }\n endWithError(error as Error);\n }\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { connectToCluster, getCurrentNamespace } from '../../utils/index.js';\nimport { fillMissingRequiredValues } from '../../utils/inquirer.js';\n\nexport default async (cluster: string, variationId?: string) => {\n await connectToCluster(cluster);\n\n if (cluster === 'expManager' || cluster === 'dev1') {\n const { variationId: namespace } = await fillMissingRequiredValues({ variationId }, ['variationId']);\n if (namespace !== '') {\n if (await getCurrentNamespace() === namespace) {\n console.log(`Already connected to simulation with uuid: ${namespace}, skipping namespace switch...`);\n process.exit(0);\n }\n await asyncSpawn('kubectl', ['config', 'set-context', '--current', `--namespace=${namespace}`], { print: false });\n console.log(`Switched to simulation with uuid: ${namespace} successfully`);\n }\n }\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { getVariationId, getLocalPort, safeSelect } from '../../utils/inquirer.js';\nimport { connectToCluster, endWithError } from '../../utils/index.js';\nimport type { Values } from '../../index.js';\n\nasync function ensureTelepresenceInstalled() {\n try {\n await asyncSpawn('telepresence', ['version'], { print: false });\n } catch {\n endWithError('Telepresence is not installed. Please install it from:\\nhttps://www.telepresence.io/docs/latest/quick-start/');\n }\n}\n\nfunction leaveOrConnect() {\n return safeSelect({\n message: 'Do you want to leave the connection or create a new one?',\n choices: [\n { name: 'Leave the current connection', value: 'leave' },\n { name: 'Create a new connection', value: 'connect' },\n ] as const,\n default: 'connect',\n });\n}\n\nexport default async function telepresenceWizard(values: Values): Promise<void> {\n await ensureTelepresenceInstalled();\n\n const { cluster = '', service = '' } = values; // Values should be defined by now, thanks to inquirer. Default to hint to TS we always have values.\n await connectToCluster(cluster);\n\n const action = await leaveOrConnect();\n if (!['leave', 'connect'].includes(action!)) {\n endWithError('Invalid action, how did you get here? 🤔');\n }\n if (action === 'leave') {\n await asyncSpawn('telepresence', ['leave', service]);\n console.log('Disconnected! 👋');\n return;\n }\n const namespace = values.variationId || await getVariationId();\n const localPort = (values['local-port'] && Number.parseInt(values['local-port'], 10)) || Number.parseInt((await getLocalPort()) || '', 10);\n await asyncSpawn('telepresence', ['connect', `--namespace=${namespace}`]);\n await asyncSpawn('telepresence', ['intercept', service, '--port', localPort.toString(), '--env-file=./.env']);\n console.log('Everything is set up! 🚀');\n console.log(`You can now access the service at localhost:${localPort}`);\n console.log('You can only have one connection at a time. If you want to connect to a different service, you need to leave the current connection first.');\n process.exit(0);\n}\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\nexport default async (prefix: string, help: string, service?: string) => {\n if (!service) {\n endWithError(new Error('service is required for exposeService'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n }\n await asyncSpawn('kubectl', ['patch', 'svc', prefix, service, '-p', '{\"spec\": {\"type\": \"LoadBalancer\"}}']);\n console.log(`exposed ${service} successfully. the service is now creating an internal load balancer ip to use with vpn`);\n process.exit(0);\n};\n","import { setTimeout } from 'node:timers/promises';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\ninterface Values {\n 'local-port'?: string;\n}\n\nexport default async (values: Values, prefix: string, variationId: string, help: string, service?: string) => {\n const localPort = Number.parseInt(values['local-port'] ?? '5432', 10);\n if (Number.isNaN(localPort)) {\n endWithError(new Error('if defined, local-port must be a number'), help);\n }\n const DB_PASSWORD = `afpass_${variationId}`;\n const USER_NAME = 'postgres';\n const variationUnderScore = variationId.replaceAll('-', '_');\n const DB_NAME = service ? `${service.replaceAll('-', '_') || ''}_${variationUnderScore}` : 'postgres';\n\n const postgressPath = `postgres://${USER_NAME}:${DB_PASSWORD}@localhost:${localPort}/${DB_NAME}?&nickname=var_${variationId}`;\n console.log(`Forwarding db to local port ${localPort}.\\naccess the DB at ${postgressPath}\\nPress ctrl+c to stop.`);\n\n const dbEnvs = ` DB_USERNAME=${USER_NAME}\n DB_PASSWORD=${DB_PASSWORD}\n DB_NAME=${service ? DB_NAME : `<service_name>_${variationUnderScore}`}`;\n console.log('Generated database environment for local development:\\n', dbEnvs);\n\n setTimeout(1500).then(() => asyncSpawn('open', [postgressPath], { print: false })).catch(() => null);\n await asyncSpawn('kubectl', [prefix, 'port-forward', `statefulset/p${variationId}-postgresql`, `${localPort}:5432`], { print: false });\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { endWithError } from '../../utils/index.js';\n\ninterface Values {\n port?: string;\n 'local-port'?: string;\n}\n\nexport default async (values: Values, prefix: string, help: string, service?: string) => {\n const port = Number.parseInt(values.port ?? '8080', 10);\n const localPort = Number.parseInt(values['local-port'] ?? '', 10) || port;\n if (!service) {\n endWithError(new Error('service is required for forwardService'), help);\n }\n if (!port || Number.isNaN(port)) {\n endWithError(new Error('port is required and must be a numbers'), help);\n }\n if (localPort && Number.isNaN(localPort)) {\n endWithError(new Error('local-port must be a number'), help);\n }\n let { stdout: podName } = await asyncSpawn('kubectl', ['get', 'pods', prefix, '-l', `service=${service}`, '-o', 'jsonpath=\"{.items[0].metadata.name}\"'], { print: false });\n podName &&= podName.trim();\n if (!podName) {\n endWithError(new Error(`No pods found for service ${service}`));\n }\n if (podName.startsWith('\"') && podName.endsWith('\"')) {\n podName = podName.slice(1, -1);\n }\n console.log(`Found pod ${podName}, serving locally on port ${localPort} from remote port ${port}.\\nPress ctrl+c to stop.`);\n await asyncSpawn('kubectl', ['port-forward', prefix, podName, `${localPort}:${port}`], { print: false });\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { parseIps } from '../../utils/index.js';\n\nexport default async (prefix: string) => {\n const { stdout } = await asyncSpawn('kubectl', [prefix, 'get', 'services'], { print: false });\n const ips = parseIps(stdout);\n ips.forEach(ip => console.log(ip));\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\n\nexport default async (prefix: string, variationId: string) => {\n const SIMULATION_CLUSTER_FRONT = 'simulation-cluster-front';\n await asyncSpawn('kubectl', ['annotate', prefix, 'service', SIMULATION_CLUSTER_FRONT, 'cloud.google.com/load-balancer-type-']);\n await asyncSpawn('kubectl', ['patch', 'svc', prefix, SIMULATION_CLUSTER_FRONT, '-p', '{\"spec\": {\"type\": \"LoadBalancer\"}}']);\n await asyncSpawn('kubectl', ['create', prefix, 'rolebinding', 'admin', '--clusterrole=cluster-admin', `--serviceaccount=${variationId}:default`]);\n console.log(`Successfully exposed ${SIMULATION_CLUSTER_FRONT} and added role binding to dispatch simulations`);\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\n\nexport default async () => {\n const getArgs = (dataKey: string) => ['get', 'secret', 'rabbitmq-default-user', '-o', `jsonpath=\"{.data.${dataKey}}\"`];\n const [{ stdout: username }, { stdout: password }] = await Promise.all([\n asyncSpawn('kubectl', getArgs('username'), { print: false }),\n asyncSpawn('kubectl', getArgs('password'), { print: false }),\n ]);\n console.log(`username: ${Buffer.from(username, 'base64').toString('ascii')}`);\n console.log(`password: ${Buffer.from(password, 'base64').toString('ascii')}`);\n process.exit(0);\n};\n","import asyncSpawn from '../../utils/asyncSpawn.js';\nimport { basename } from 'node:path';\nimport { cwd } from 'node:process';\nimport { getCurrentBranch } from '../../utils/git.js';\n\nexport default async (prefix: string) => {\n const dir = basename(cwd());\n const [branchName, archResult] = await Promise.all([getCurrentBranch(), asyncSpawn('uname', ['-m'], { print: false })]);\n const arch = archResult.stdout.trim();\n const dateSuffix = `${new Date().getHours().toString().padStart(2, '0')}-${new Date().getMinutes().toString().padStart(2, '0')}-${new Date().getSeconds().toString().padStart(2, '0')}`;\n const imageName = `gcr.io/autofleetprod/${dir}:${branchName}-${dateSuffix}`;\n console.log(`Building and pushing image ${imageName}`);\n const platformFlag = arch === 'x86_64' ? [] : ['--platform', 'linux/amd64'];\n await asyncSpawn('docker', ['build', '.', ...platformFlag, '-t', imageName, '--build-arg', `NPM_TOKEN=${process.env.NPM_TOKEN}`]);\n await asyncSpawn('docker', ['push', imageName]);\n const { stdout: podDescription } = await asyncSpawn('kubectl', ['describe', 'pod', prefix, '-l', `service=${dir}`], { print: false });\n if (podDescription.includes('Init Containers:')) {\n await asyncSpawn('kubectl', ['patch', `deployment/${dir}`, prefix, '--patch', `{\"spec\": {\"template\": {\"spec\": {\"initContainers\": [{\"name\": \"init\",\"image\": \"${imageName}\"}]}}}}`]);\n }\n await asyncSpawn('kubectl', ['set', 'image', `deployment/${dir}`, `worker=${imageName}`, prefix]);\n await asyncSpawn('kubectl', ['rollout', 'status', 'deployments', dir, prefix]);\n process.exit(0);\n};\n","import { basename } from 'node:path';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { getGitPath } from '../../utils/git.js';\nimport { endWithError } from '../../utils/index.js';\nimport { setEnvValue } from '../../utils/env.js';\n\nexport default async (prefix: string, cluster: string, variationId: string) => {\n const LOCAL_ENV_NAME = 'LOCAL_ENV_NAME';\n const API_GATEWAY_MS = 'api-gateway-ms';\n const CONTROL_CENTER_MS = 'control-center-ms';\n const envNameToUse = cluster === 'staging' ? 'staging' : `simulator-${variationId}`;\n\n const repoPath = await getGitPath();\n if (basename(repoPath) !== 'control-center') {\n endWithError(new Error('The `localDev` command must be run from the control-center repository'));\n }\n const { stdout: apiGatewayMsIP } = await asyncSpawn('kubectl', ['get', 'ingress', `${API_GATEWAY_MS}-ingress`, prefix, '-o', 'jsonpath=\"{.status.loadBalancer.ingress[0].ip}\"'], { print: false });\n if (!apiGatewayMsIP) {\n endWithError(new Error(`The IP of the Load balancer for ${API_GATEWAY_MS} was not found`));\n }\n const changedIP = await setEnvValue(repoPath, 'API_GATEWAY_MS_SERVICE_HOST', apiGatewayMsIP.replace(/\"/g, ''));\n const changedEnvName = await setEnvValue(repoPath, LOCAL_ENV_NAME, envNameToUse);\n const msg = `${\n changedIP ? `Updated .env file to use ${API_GATEWAY_MS} IP (${apiGatewayMsIP}).\\n` : ''\n }${\n changedEnvName ? `Updated .env file ${LOCAL_ENV_NAME} to ${envNameToUse} (used for firebase setup).\\n` : ''\n }Port-forwarding of ${CONTROL_CENTER_MS} will now start to port 8085.\\nPress ctrl+c to stop.`;\n console.log(msg);\n await asyncSpawn('kubectl', ['port-forward', prefix, `svc/${CONTROL_CENTER_MS}`, '8085:80'], { print: false });\n process.exit(0);\n};\n","import { EOL } from 'node:os';\nimport { resolve } from 'node:path';\nimport { readFile, writeFile } from 'node:fs/promises';\n\nexport async function setEnvValue(repoRoot: string, key: string, value: string): Promise<boolean> {\n const filePath = resolve(repoRoot, '.env');\n const envFileContent = await readFile(filePath, 'utf8');\n const envVars = envFileContent.split(EOL);\n\n // (?<!#\\\\s*) Negative lookbehind to avoid matching comments (lines that starts with #).\n // There is a double slash in the RegExp constructor to escape it.\n // (?==) Positive lookahead to check if there is an equal sign right after the key.\n // This is to prevent matching keys prefixed with the key of the env var to update.\n const regexString = `(?<!#\\\\s*)${key}(?==)`;\n const matchingLine = envVars.find((line: string) => line.match(regexString));\n\n if (matchingLine?.split('=').at(-1) === value) {\n return false;\n }\n\n const target = matchingLine ? envVars.indexOf(matchingLine) : -1;\n\n if (target !== -1) {\n envVars.splice(target, 1, `${key}=${value}`);\n } else {\n envVars.push(`${key}=${value}`);\n }\n\n await writeFile(filePath, envVars.join(EOL));\n return true;\n}\n","import { resolve } from 'node:path';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { isPathIgnored } from '../../utils/git.js';\nimport { writeMirrordFile, MIRRORD_FOLDER_NAME } from '../../utils/mirrord.js';\n\nasync function addToGitIgnore(mirrordPath: string) {\n const isIgnored = await isPathIgnored(MIRRORD_FOLDER_NAME);\n if (isIgnored) {\n return;\n }\n const gitIgnoreFile = resolve(mirrordPath, '..', '..', '.gitignore');\n const gitIgnoreFileContent = await readFile(gitIgnoreFile, 'utf8');\n const gitIgnoreFileContentLines = gitIgnoreFileContent.split('\\n').filter(Boolean);\n gitIgnoreFileContentLines.push(MIRRORD_FOLDER_NAME);\n await writeFile(gitIgnoreFile, `${gitIgnoreFileContentLines.join('\\n')}\\n`);\n}\n\nexport default async (variationId?: string) => {\n const { mirrordConfigData, mirrordPath } = await writeMirrordFile(variationId);\n await addToGitIgnore(mirrordPath);\n console.log('Wrote the default mirrord config for the requested variation ID', { mirrordConfigData });\n process.exit(0);\n};\n","import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\n\nconst dockerComposeFile = `\nservices:\n redis:\n image: redis:6\n ports:\n - \"6379:6379\"\n volumes:\n - redis_data:/data\n command: redis-server --appendonly yes\n\n rabbitmq:\n image: rabbitmq:3.12.13-management\n ports:\n - \"5672:5672\" # AMQP protocol port\n - \"15672:15672\" # Management UI port\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n environment:\n - RABBITMQ_DEFAULT_USER=guest\n - RABBITMQ_DEFAULT_PASS=guest\n\n postgres:\n image: postgis/postgis:14-3.3\n platform: linux/amd64\n ports:\n - \"5432:5432\"\n volumes:\n - postgres_data:/var/lib/postgresql/data\n environment:\n - POSTGRES_DB=postgres\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=postgres\n\n elasticsearch:\n image: docker.elastic.co/elasticsearch/elasticsearch:8.8.1\n ports:\n - \"9200:9200\"\n - \"9300:9300\"\n environment:\n - discovery.type=single-node\n - xpack.security.enabled=false\n - xpack.security.transport.ssl.enabled=false\n - xpack.security.http.ssl.enabled=false\n - ES_JAVA_OPTS=-Xms1g -Xmx1g\n volumes:\n - elasticsearch_data:/usr/share/elasticsearch/data\n ulimits:\n memlock:\n soft: -1\n hard: -1\n mem_limit: 2g\n\n kibana:\n image: docker.elastic.co/kibana/kibana:8.8.1\n ports:\n - \"5601:5601\"\n environment:\n - ELASTICSEARCH_HOSTS=http://elasticsearch:9200\n depends_on:\n - elasticsearch\n\nvolumes:\n redis_data:\n rabbitmq_data:\n postgres_data:\n elasticsearch_data:\n`;\n\nexport default async () => {\n const dockerComposePath = path.join(os.tmpdir(), 'docker-compose.yml');\n fs.writeFileSync(dockerComposePath, dockerComposeFile);\n await asyncSpawn('docker-compose', ['-f', dockerComposePath, 'up', '-d'], { print: false });\n console.log('--------------------------------------------------------------------------------');\n console.log('Successfully started the services:\\n');\n console.log('redis: localhost:6379 🚀');\n console.log('postgres: localhost:5432, user: postgres, password: postgres 🐘');\n console.log('rabbitmq: localhost:5672 and http://localhost:15672, user: guest, password: guest 🐇');\n console.log('elasticsearch: localhost:9200 ❓');\n console.log('kibana: http://localhost:5601 ❓');\n process.exit(0);\n};\n","import { spawn } from 'node:child_process';\nimport asyncSpawn from '../../utils/asyncSpawn.js';\nimport { connectToCluster, getRedisRegion, isSimulationCluster } from '../../utils/index.js';\nimport { safeSelect } from '../../utils/inquirer.js';\nimport { createDeferredPromise } from '../../utils/promise.js';\n\ninterface RedisInstance {\n displayName?: string;\n host: string;\n name: string;\n}\n\nexport default async (clusterName: string) => {\n if (isSimulationCluster(clusterName)) {\n console.error('Connecting to Redis is not supported for simulation clusters (need to be added)');\n process.exit(1);\n }\n\n const {\n project,\n name,\n } = await connectToCluster(clusterName);\n const redisRegion = getRedisRegion(clusterName);\n const { stdout: redisInstances } = await asyncSpawn('gcloud', ['redis', 'instances', 'list', '--region', redisRegion, '--project', project || name, '--format', 'json'], { print: false });\n let redisInstancesJson;\n try {\n redisInstancesJson = JSON.parse(redisInstances) as RedisInstance[];\n } catch (e) {\n console.error('Failed to parse redis instances', { redisInstances, e });\n process.exit(1);\n }\n\n const redisNameToIpMap = Object.fromEntries(redisInstancesJson.map((instance: RedisInstance) => {\n const redisPath = instance.name.split('/');\n return [instance.displayName || redisPath?.at(-1) || instance.name, instance.host];\n }));\n\n const redisIp = await safeSelect({\n message: 'which redis instance do you want to connect to?',\n choices: Object.entries(redisNameToIpMap).map(([name, ip]) => ({ name, value: ip })),\n default: Object.keys(redisNameToIpMap)[0],\n });\n\n if (!redisIp) {\n console.error('No redis instance selected');\n process.exit(1);\n }\n\n const { stdout: allPodsName } = await asyncSpawn('kubectl', ['get', 'pods', '--no-headers', '-o', 'custom-columns=:metadata.name'], { print: false });\n const redisPodName = allPodsName.split('\\n').find(podName => podName.includes('redis'));\n\n if (!redisPodName?.trim()) {\n console.error('No redis pod found');\n process.exit(1);\n }\n\n try {\n const { promise, resolve, reject } = createDeferredPromise<void>();\n const shell = spawn('kubectl', [\n 'exec',\n '-it',\n redisPodName,\n '--',\n 'redis-cli',\n '-h',\n redisIp,\n ], {\n stdio: 'inherit',\n shell: true,\n });\n shell.on('exit', (code) => {\n if (code !== 0) {\n reject(new Error(`Process exited with code ${code}`));\n } else {\n resolve();\n }\n });\n shell.on('error', (error) => {\n console.error('Process error:', error);\n reject(error);\n });\n\n console.log('Connecting to Redis... Could take a few seconds ⏱️');\n\n await promise;\n\n process.exit(0);\n } catch (error) {\n console.error('Failed to connect to Redis:', error);\n process.exit(1);\n }\n};\n","#!/usr/bin/env node\nimport parseArgs from './utils/parser.js';\nimport {\n SUPPORTED_CLUSTERS,\n connectAndGetPrefix, endWithError,\n} from './utils/index.js';\nimport { fillMissingRequiredValues } from './utils/inquirer.js';\nimport { getVariationIdFromMirrodConfig } from './utils/mirrord.js';\nimport {\n mirrord,\n switchCluster,\n telepresenceWizard,\n enableSimulator,\n exposeService,\n forwardDb,\n forwardService,\n getIps,\n localDev,\n rabbitCreds,\n updateExp,\n mirrordConfig,\n dockerInit,\n openRedis,\n} from './commands/index.js';\n\nconst clusterOptions = SUPPORTED_CLUSTERS.join('/');\nconst variationAndCluster = `--variationId=<yourVariationUuid> --cluster=<${clusterOptions}>`;\n\nconst COMMANDS = {\n switchCluster: variationAndCluster,\n exposeService: `--service=<driver-ms> ${variationAndCluster}`,\n forwardDb: `${variationAndCluster} --local-port=<localPort>`,\n forwardService: `--service=<driver-ms> ${variationAndCluster} --port=<port> --local-port=<localPort>`,\n getIps: variationAndCluster,\n enableSimulator: variationAndCluster,\n rabbitCreds: variationAndCluster,\n updateExp: variationAndCluster,\n telepresenceWizard: `--service=<driver-ms> ${variationAndCluster} --local-port=<localPort>`,\n localDev: variationAndCluster,\n mirrord: `--service=<driver-ms> ${variationAndCluster}`,\n mirrordConfig: '--variationId=<yourVariationUuid>',\n dockerInit: '',\n openRedis: '--cluster=<${clusterOptions}',\n};\ntype Command = keyof typeof COMMANDS;\nconst isCommand = (c: string): c is Command => Object.keys(COMMANDS).includes(c);\n\nconst { positionals, values, help } = parseArgs({\n strict: true,\n binName: 'autofleet',\n allowPositionals: true,\n options: {\n cluster: {\n type: 'string',\n short: 'c',\n description: 'The cluster name. One of dev1, e2eManager, expManager',\n },\n variationId: {\n type: 'string',\n short: 'i',\n description: 'The variation id',\n },\n service: {\n type: 'string',\n short: 's',\n description: 'The service name',\n },\n port: {\n type: 'string',\n short: 'p',\n description: 'The remote port to forward',\n },\n 'local-port': {\n type: 'string',\n short: 'l',\n description: 'The local port to forward to',\n },\n 'prefer-pod': {\n type: 'boolean',\n short: 'r',\n default: false,\n description: 'Wether the mirrord command should run against the pod, rather than the deployment.',\n },\n },\n commands: COMMANDS,\n});\n\nexport type Values = typeof values;\ntype ValueWithDefault<T = keyof Values> = T | { option: T; defaultVal: string };\n\nif (!positionals.length) {\n console.log(help);\n process.exit(0);\n}\n\nif (positionals.length > 1) {\n endWithError('Only one command is allowed', help);\n}\n\nconst [command] = positionals;\nif (!isCommand(command)) {\n endWithError(new Error(`Command ${command} does not exist`), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nconst COMMAND_REQUIRED_VALUES_MAP: Partial<Record<Command, ValueWithDefault[]>> = {\n switchCluster: ['cluster'],\n exposeService: ['cluster', 'variationId', 'service'],\n forwardDb: ['cluster', 'variationId', { option: 'local-port', defaultVal: '5432' }],\n forwardService: ['cluster', 'variationId', 'service', 'port'],\n telepresenceWizard: ['cluster', 'service'],\n mirrordConfig: ['variationId'],\n mirrord: ['cluster', { option: 'variationId', defaultVal: command === 'mirrord' ? await getVariationIdFromMirrodConfig() : '' }, 'service'],\n dockerInit: [],\n openRedis: ['cluster'],\n};\n\nawait fillMissingRequiredValues(\n values,\n COMMAND_REQUIRED_VALUES_MAP[command] ?? ['cluster', 'variationId'],\n);\nconst { cluster, variationId, service } = values;\n\nswitch (command) {\ncase 'mirrordConfig':\n await mirrordConfig(variationId);\n break;\ncase 'dockerInit':\n await dockerInit();\n break;\n}\n\nif (!cluster) {\n endWithError(new Error('cluster required'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nswitch (command) {\ncase 'telepresenceWizard':\n await telepresenceWizard(values);\n break;\ncase 'switchCluster':\n await switchCluster(cluster, variationId);\n break;\ncase 'openRedis':\n await openRedis(cluster);\n break;\n}\n\nif (!variationId) {\n endWithError(new Error('variationId required'), help);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n process.exit(1);\n}\nlet prefix: string;\ntry {\n prefix = await connectAndGetPrefix({ clusterName: cluster, variationId });\n} catch (error) {\n endWithError(error as Error);\n throw new Error('Typescript is not clever enough to understand that endWithError will exit the process');\n}\n\nswitch (command) {\ncase 'mirrord':\n await mirrord(prefix, variationId, service);\n break;\ncase 'exposeService':\n await exposeService(prefix, help, service);\n break;\ncase 'forwardDb':\n await forwardDb(values, prefix, variationId, help, service);\n break;\ncase 'forwardService':\n await forwardService(values, prefix, help, service);\n break;\ncase 'getIps':\n await getIps(prefix);\n break;\ncase 'enableSimulator':\n await enableSimulator(prefix, variationId);\n break;\ncase 'rabbitCreds':\n await rabbitCreds();\n break;\ncase 'updateExp':\n await updateExp(prefix);\n break;\ncase 'localDev':\n await localDev(prefix, cluster, variationId);\n break;\n}\n"],"mappings":"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","names":["join","randomUUID","mkdir","writeFile","readFile","MIRRORD_FOLDER_NAME","getMirrodFolderPath","makeDir","repoPath","getGitPath","mirrordPath","join","writeMirrordFile","variationId","mirrordConfigData","randomUUID","getVariationIdFromMirrodConfig","mirrordConfigDataString","registerProcessForCleanup","onExit","trimProbeString","str","LIVENESS_PROBE","READINESS_PROBE","WORKER_PATH","leaf","SET_PROBE_VALUES","probeAndValues","probe","value","mirrord_default","prefix","variationId","service","livenessProbe","readinessProbe","asyncSpawn_default","abortController","registerProcessForCleanup","error","endWithError","switchCluster_default","cluster","variationId","connectToCluster","namespace","fillMissingRequiredValues","getCurrentNamespace","asyncSpawn_default","ensureTelepresenceInstalled","asyncSpawn_default","endWithError","leaveOrConnect","safeSelect","telepresenceWizard","values","cluster","service","connectToCluster","action","namespace","getVariationId","localPort","getLocalPort","exposeService_default","prefix","help","service","endWithError","asyncSpawn_default","setTimeout","forwardDb_default","values","prefix","variationId","help","service","localPort","endWithError","DB_PASSWORD","USER_NAME","variationUnderScore","DB_NAME","postgressPath","dbEnvs","setTimeout","asyncSpawn_default","forwardService_default","values","prefix","help","service","port","localPort","endWithError","podName","asyncSpawn_default","getIps_default","prefix","stdout","asyncSpawn_default","parseIps","ip","enableSimulator_default","prefix","variationId","SIMULATION_CLUSTER_FRONT","asyncSpawn_default","rabbitCreds_default","getArgs","dataKey","username","password","asyncSpawn_default","basename","cwd","updateExp_default","prefix","dir","basename","cwd","branchName","archResult","getCurrentBranch","asyncSpawn_default","arch","dateSuffix","imageName","podDescription","basename","EOL","resolve","readFile","writeFile","setEnvValue","repoRoot","key","value","filePath","envVars","regexString","matchingLine","line","target","localDev_default","prefix","cluster","variationId","LOCAL_ENV_NAME","API_GATEWAY_MS","CONTROL_CENTER_MS","envNameToUse","repoPath","getGitPath","basename","endWithError","apiGatewayMsIP","asyncSpawn_default","changedIP","setEnvValue","changedEnvName","msg","resolve","readFile","writeFile","addToGitIgnore","mirrordPath","isPathIgnored","MIRRORD_FOLDER_NAME","gitIgnoreFile","resolve","gitIgnoreFileContentLines","readFile","writeFile","mirrordConfig_default","variationId","mirrordConfigData","writeMirrordFile","path","fs","os","dockerComposeFile","dockerInit_default","dockerComposePath","asyncSpawn_default","spawn","openRedis_default","clusterName","isSimulationCluster","project","name","connectToCluster","redisRegion","getRedisRegion","redisInstances","asyncSpawn_default","redisInstancesJson","e","redisNameToIpMap","instance","redisPath","redisIp","safeSelect","ip","allPodsName","redisPodName","podName","promise","resolve","reject","createDeferredPromise","shell","spawn","code","error","clusterOptions","SUPPORTED_CLUSTERS","variationAndCluster","COMMANDS","isCommand","c","positionals","values","help","parseArgs","endWithError","command","COMMAND_REQUIRED_VALUES_MAP","getVariationIdFromMirrodConfig","fillMissingRequiredValues","cluster","variationId","service","mirrordConfig_default","dockerInit_default","telepresenceWizard","switchCluster_default","openRedis_default","prefix","connectAndGetPrefix","error","mirrord_default","exposeService_default","forwardDb_default","forwardService_default","getIps_default","enableSimulator_default","rabbitCreds_default","updateExp_default","localDev_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/cli",
3
- "version": "2.11.3",
3
+ "version": "2.13.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/readme.md CHANGED
@@ -11,6 +11,8 @@ To test the CLI on your local environment, follow these steps:
11
11
 
12
12
  ## Available Commands
13
13
 
14
+ ### autofleet (`autofleet <command>`)
15
+
14
16
  | Command | Description |
15
17
  |----------------------|-----------------------------------------------------------------------------|
16
18
  | **switchCluster** | Switches the connected Kubernetes (K8S) cluster. With option to switch to specific simulation |
@@ -27,3 +29,12 @@ To test the CLI on your local environment, follow these steps:
27
29
  | **dockerInit** | Create docker containers for Postgres, Redis and Rabbit locally. |
28
30
  | **openRedis** | Open redis cli for a specific redis instance in a specific cluster |
29
31
  | ~~**telepresenceWizard**~~ | Used to set up a connection via Telepresence for debugging before Mirrord. This is deprecated. |
32
+
33
+
34
+ ### git (`git autofleet <command>`)
35
+
36
+ | Command | Description |
37
+ |----------------------|-----------------------------------------------------------------------------|
38
+ | **bumpVersion** | Bumps the version, and commits the package and package-lock files. Make sure your git stage is clear, and you have no further changes within these files |
39
+ | **openPR** | Open PR for the current branch. |
40
+ | **releaseBeta** | Builds the package, bumps the version and releases to a beta tag |
@@ -1,14 +0,0 @@
1
- var A=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),R=e=>{throw TypeError(e)};var O=(e,t,r)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&R("Object expected");var n,s;r&&(n=t[A("asyncDispose")]),n===void 0&&(n=t[A("dispose")],r&&(s=n)),typeof n!="function"&&R("Object not disposable"),s&&(n=function(){try{s.call(this)}catch(i){return Promise.reject(i)}}),e.push([r,n,t])}else r&&e.push([r]);return t},$=(e,t,r)=>{var n=typeof SuppressedError=="function"?SuppressedError:function(o,a,p,c){return c=Error(p),c.name="SuppressedError",c.error=o,c.suppressed=a,c},s=o=>t=r?new n(o,t,"An error was suppressed during disposal"):(r=!0,o),i=o=>{for(;o=e.pop();)try{var a=o[1]&&o[1].call(o[2]);if(o[0])return Promise.resolve(a).then(i,p=>(s(p),i()))}catch(p){s(p)}if(r)throw t};return i()};import{parseArgs as W}from"node:util";var j={name:"@autofleet/cli",version:"2.11.3",description:"",main:"dist/index.js",scripts:{start:"tsx bin/index.ts",dev:"tsup --watch",build:"tsup",linter:"eslint .",test:"vitest",coverage:"vitest --coverage"},devDependencies:{tsup:"^8.3.0",tsx:"^4.19.1"},bin:{autofleet:"./dist/index.js","autofleet-e2e":"./dist/e2e.js","git-autofleet":"./dist/git-autofleet.js"},engines:{node:">= 18.3.0"},type:"module",author:"Autofleet",license:"ISC",dependencies:{"@inquirer/prompts":"^5.0.2","p-retry":"^6.2.0"},optionalDependencies:{"@rollup/rollup-linux-x64-gnu":"*"}};var q={help:{type:"boolean",short:"h",default:!1,description:"Show help (prints this message)"},version:{type:"boolean",short:"v",default:!1,description:"Show version number"}};function B(e){e.options={...q,...e.options};let t=W(e),{values:r}=t;r.version&&(console.log(j.version),process.exit(0));let n=e.commands?`
2
-
3
- Commands:
4
- ${Object.entries(e.commands).map(([o,a])=>`${o.padEnd(30," ")} ${a}`).join(`
5
- `)}
6
- `:"",s=Math.max.apply(null,Object.values(e.options).map(({description:o})=>o.length)),i=`
7
- ${e.binName} ${n?"[command] ":""}<options>${n}
8
- Options:
9
- ${Object.entries(e.options).map(([o,{description:a,type:p,short:c}])=>`${(c?`--${o}, -${c}`:`--${o}`).padEnd(30," ")} ${a.padEnd(s+10," ")} [${p}]`).join(`
10
- `)}
11
- `;return r.help&&(console.log(i),process.exit(0)),{...t,help:i}}import{spawn as J}from"node:child_process";var L=()=>{if(Promise.withResolvers)return Promise.withResolvers();let e,t;return{promise:new Promise((n,s)=>{e=s,t=n}),reject:e,resolve:t}};var f=async(e,t,{print:r=!0,env:n={},signal:s,shell:i}={})=>{typeof t=="boolean"&&(r=t,t=void 0);let o=new Error,a=o.stack?o.stack.replace(/^.*/," ..."):null,{promise:p,reject:c,resolve:y}=L(),l=J(e,t,{env:Object.assign(n,process.env),signal:s,shell:i});r&&(l.stdout.pipe(process.stdout),l.stderr.pipe(process.stderr));let d="",P="";l.stdout?.on("data",u=>{d+=u}),l.stderr?.on("data",u=>{P+=u});let _=r?"exit":"close";function w(u){l.removeListener(_,S),Object.assign(u,{pid:l.pid,stdout:d,stderr:P,status:null,signal:null}),c(u)}function S(u,h){l.removeListener("error",w);let C={pid:l.pid,stdout:d,stderr:P,status:u,signal:h};if(u!==0){let b=typeof t!="boolean"&&` ${t?.join(" ")}`||"",m=h?new Error(`${e}${b} exited with signal: ${h}`):new Error(`${e}${b} exited with non-zero code: ${u}`);m.stack&&a&&(m.stack+=`
12
- ${a}`),Object.assign(m,C),c(m)}else y(C)}return l.once(_,S),l.once("error",w),p};var ve=async()=>{let{stdout:e}=await f("git",["branch","--show-current"],{print:!1});return e.trim()},k=async()=>{let{stdout:e}=await f("git",["rev-parse","--show-toplevel"],{print:!1});return e.trim()},xe=async e=>{let{stdout:t}=await f("git",["diff","origin/master..",e],{print:!1});return t},_e=async e=>{try{return await f("git",["check-ignore",e],{print:!1}),!0}catch{return!1}};import{confirm as Y,input as v,select as ee}from"@inquirer/prompts";import M from"node:fs";var z="SERVICE_HOST",I={prodUs:["us-autofleet-production","us-central1","autofleet-production"],prodEu:["autofleetprod","europe-west1","autofleetprod"],prodJp:["jp-autofleet-production","asia-northeast1","autofleet-japan"]},U={dev1:["dev-cluster-2","europe-west1","dev1-experiment-manager"],e2eManager:["e2e-cluster-2","europe-west1","e2e-project-1"],expManager:["af-experiment-manager","europe-west1"]},H={staging:["autofleet-staging","europe-west1-b"],loadTest:["lt-autofleet-production","asia-northeast1","load-testing-428806"]},E={...I,...U,...H},X={staging:"europe-west1"},V=Object.keys(E),Z=async e=>{let t=E[e];if(!t)throw new Error(`Cluster name ${e} does not exist!`);let[r,n,s]=t;return I[e]&&!await D(`\u274C\u274C Are you sure you want to run this command on ${e}? \u274C\u274C`,!1)?(console.log("Aborting..."),process.exit(1)):{name:r,region:n,project:s}},Ae=({newFilePath:e,filePath:t,linesToReplace:r})=>{let n=M.readFileSync(t,"utf8");for(let{find:s,replace:i}of r)n=n.replace(s,i);M.writeFileSync(e,n)};async function K(){try{let{stdout:e}=await f("kubectl",["config","current-context"],{print:!1});return e.trim()}catch{return null}}var Q=async e=>{let{name:t,region:r,project:n}=await Z(e),s=`gke_${n||t}_${r}_${t}`;return await K()===s?(console.log(`Already connected to ${e}, skipping connection to cluster...`),{name:t,region:r,project:n}):(await f("gcloud",["container","clusters","get-credentials",t,"--region",r,"--project",n||t],{print:!1}),console.log(`Switched to ${e} successfully`),{name:t,region:r,project:n})};async function Re(){try{let{stdout:e}=await f("kubectl",["config","view","--minify","--output","jsonpath={..namespace}"],{print:!1});return e.trim()}catch{return"default"}}var Oe=async({clusterName:e,variationId:t})=>(await Q(e),`--namespace=${t}`),$e=e=>{let t=e.split(`
13
- `).filter(Boolean);t.shift();let r=t.map(n=>{let[s,i,o,a,p,c]=n.split(/(\s+)/).map(d=>d.trim()).filter(Boolean);return`${s.replace(/-/g,"_").toUpperCase()}_${z}=${a}`});return r=r.filter(n=>!n.includes("none")&&!n.includes("undefined")),r},T=(e,t)=>(e instanceof Error||(e=new Error(e)),console.error(e),t&&console.log(t),process.exit(1)),je=e=>Object.keys(U).includes(e),Le=e=>X[e]||E[e][1];import{sep as te}from"path";Symbol.dispose??=Symbol.for("nodejs.dispose");Symbol.asyncDispose??=Symbol.for("nodejs.asyncDispose");var x,N=()=>x?.();function re(){return process.once("beforeExit",N),{[Symbol.dispose](){process.off("beforeExit",N),x=void 0}}}async function g(e,...t){try{var r=[];try{let o=O(r,re());let a=e(...t);x=a.cancel;return await a}catch(n){var s=n,i=!0}finally{$(r,s,i)}}catch(o){o instanceof Error&&["CancelPromptError","ExitPromptError"].includes(o.constructor.name)&&T("Cancelled! \u{1F44B}"),T(o)}}function ne(...e){return g(ee,...e)}var oe=e=>e.charAt(0).toUpperCase()+e.slice(1).split(/(?=[A-Z])/).join(" ");function se(){return ne({message:"Which environment do you want to use?",choices:V.map(e=>({name:oe(e),value:e})),default:"expManager"})}async function ie(){let t=(await k()).split(te).pop();return g(v,{message:"Enter the service name:",default:t})}function ae(e="default"){return g(v,{message:"Enter your simulator id (Press enter to pass):",default:e})}async function G(e="8080",t=!1){return g(v,{message:`Enter the ${t?"local ":""}port:`,default:e,validate(r){return/^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/.test(r)?!0:"Please enter a valid port number"}})}async function ce(e="5432"){return G(e,!0)}var le={cluster:se,variationId:ae,service:ie,port:(e="8080")=>G(e),"local-port":ce};async function Ve(e,t){for(let r of t){let n=typeof r=="object"?r.option:r,s=typeof r=="object"?r.defaultVal:void 0;if(typeof n!="string")throw new Error(`Invalid option ${String(n)}`);let i=le[n];if(!i)throw new Error(`No value getter for ${String(n)}`);e[n]??=await i(s)}return e}async function D(e,t=!0){return g(Y,{message:e,default:t})}export{B as a,L as b,f as c,ve as d,k as e,xe as f,_e as g,ne as h,ae as i,ce as j,Ve as k,D as l,V as m,Ae as n,Q as o,Re as p,Oe as q,$e as r,T as s,je as t,Le as u};
14
- //# sourceMappingURL=chunk-UNZ32NZN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../bin/utils/parser.ts","../package.json","../bin/utils/asyncSpawn.ts","../bin/utils/promise.ts","../bin/utils/git.ts","../bin/utils/inquirer.ts","../bin/utils/index.ts"],"sourcesContent":["import { parseArgs as nativeParseArgs, ParseArgsConfig } from 'node:util';\nimport packageJson from '../../package.json' with { type: 'json' };\n\ntype ParseArgsOptionConfig = NonNullable<ParseArgsConfig['options']>[string] & { description: string };\ntype ParseArgsParams = Omit<ParseArgsConfig, 'options'> & { binName: string; options: Record<string, ParseArgsOptionConfig>; commands?: Record<string, string> };\n\nconst GLOBAL_OPTIONS = {\n help: {\n type: 'boolean',\n short: 'h',\n default: false,\n description: 'Show help (prints this message)',\n },\n version: {\n type: 'boolean',\n short: 'v',\n default: false,\n description: 'Show version number',\n },\n} satisfies ParseArgsParams['options'];\n\ntype Expanded<T extends ParseArgsParams> = T & { options: T['options'] & typeof GLOBAL_OPTIONS };\ntype Parsed<T extends ParseArgsParams> = ReturnType<typeof nativeParseArgs<Expanded<T>>> & { help: string };\n\nexport default function parseArgs<T extends ParseArgsParams = ParseArgsParams>(params: T): Parsed<T> {\n params.options = { ...GLOBAL_OPTIONS, ...params.options };\n const data = nativeParseArgs(params as Expanded<T>);\n const { values } = data;\n if ((values as { version: boolean }).version) {\n console.log(packageJson.version);\n process.exit(0);\n }\n\n const commands = !params.commands ? '' : `\n\nCommands:\n ${Object.entries(params.commands).map(([command, example]) => `${command.padEnd(30, ' ')} ${example}`).join('\\n ')}\n`;\n\n const longestDescriptionLength = Math.max.apply(null, Object.values(params.options).map(({ description }) => description.length));\n\n const help = `\n${params.binName} ${commands ? '[command] ' : ''}<options>${commands}\nOptions:\n ${Object.entries(params.options).map(([option, { description, type, short }]) => {\n const key = short ? `--${option}, -${short}` : `--${option}`;\n return `${key.padEnd(30, ' ')} ${description.padEnd(longestDescriptionLength + 10, ' ')} [${type}]`;\n }).join('\\n ')}\n`;\n\n if ((values as { help: boolean }).help) {\n console.log(help);\n process.exit(0);\n }\n\n return { ...data, help };\n}\n","{\n \"name\": \"@autofleet/cli\",\n \"version\": \"2.11.3\",\n \"description\": \"\",\n \"main\": \"dist/index.js\",\n \"scripts\": {\n \"start\": \"tsx bin/index.ts\",\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"linter\": \"eslint .\",\n \"test\": \"vitest\",\n \"coverage\": \"vitest --coverage\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.3.0\",\n \"tsx\": \"^4.19.1\"\n },\n \"bin\": {\n \"autofleet\": \"./dist/index.js\",\n \"autofleet-e2e\": \"./dist/e2e.js\",\n \"git-autofleet\": \"./dist/git-autofleet.js\"\n },\n \"engines\": {\n \"node\": \">= 18.3.0\"\n },\n \"type\": \"module\",\n \"author\": \"Autofleet\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"@inquirer/prompts\": \"^5.0.2\",\n \"p-retry\": \"^6.2.0\"\n },\n \"optionalDependencies\": {\n \"@rollup/rollup-linux-x64-gnu\": \"*\"\n }\n}\n","import { spawn } from 'node:child_process';\nimport { createDeferredPromise } from './promise.js';\n\ninterface SpawnResult {\n pid?: number;\n stdout: string;\n stderr: string;\n status: number | null;\n signal: string | null;\n}\n\nexport default async (\n command: string, args?: boolean | readonly string[], { print = true, env = {}, signal, shell }: { print?: boolean; env?: NodeJS.ProcessEnv; signal?: AbortSignal; shell?: string | boolean } = {},\n) => {\n if (typeof args === 'boolean') {\n print = args;\n args = undefined;\n }\n const stubError = new Error();\n const callerStack = stubError.stack ? stubError.stack.replace(/^.*/, ' ...') : null;\n const { promise, reject, resolve } = createDeferredPromise<SpawnResult>();\n const child = spawn(command, args, { env: Object.assign(env, process.env), signal, shell });\n if (print) {\n child.stdout.pipe(process.stdout);\n child.stderr.pipe(process.stderr);\n }\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (data) => {\n stdout += data;\n });\n child.stderr?.on('data', (data) => {\n stderr += data;\n });\n const completionEventName = print ? 'exit' : 'close';\n function errorListener(error: Error) {\n child.removeListener(completionEventName, completionListener);\n Object.assign(error, {\n pid: child.pid,\n stdout,\n stderr,\n status: null,\n signal: null,\n });\n reject(error);\n }\n function completionListener(code: number | null, signal: string | null) {\n child.removeListener('error', errorListener);\n const result: SpawnResult = {\n pid: child.pid,\n stdout,\n stderr,\n status: code,\n signal,\n };\n if (code !== 0) {\n const argumentString = (typeof args !== 'boolean' && ` ${args?.join(' ')}`) || '';\n const error = signal\n ? new Error(`${command}${argumentString} exited with signal: ${signal}`)\n : new Error(`${command}${argumentString} exited with non-zero code: ${code}`);\n if (error.stack && callerStack) {\n error.stack += `\\n${callerStack}`;\n }\n Object.assign(error, result);\n reject(error);\n } else {\n resolve(result);\n }\n }\n\n child.once(completionEventName, completionListener);\n child.once('error', errorListener);\n return promise;\n};\n","declare global {\n interface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void; // eslint-disable-line @typescript-eslint/no-explicit-any\n }\n interface PromiseConstructor {\n /**\n * Creates a new Promise and returns it in an object, along with its resolve and reject functions.\n * @returns An object with the properties `promise`, `resolve`, and `reject`.\n *\n * ```ts\n * const { promise, resolve, reject } = Promise.withResolvers<T>();\n * ```\n */\n withResolvers<T>(): PromiseWithResolvers<T>;\n }\n}\n\nexport const createDeferredPromise = <T>() => {\n if (Promise.withResolvers) {\n return Promise.withResolvers<T>();\n }\n let reject!: PromiseWithResolvers<T>['reject'];\n let resolve!: PromiseWithResolvers<T>['resolve'];\n const promise = new Promise<T>((res, rej) => {\n reject = rej;\n resolve = res;\n });\n return { promise, reject, resolve };\n};\n","import asyncSpawn from './asyncSpawn.js';\n\nexport const getCurrentBranch = async () => {\n const { stdout: currentBranch } = await asyncSpawn('git', ['branch', '--show-current'], { print: false });\n return currentBranch.trim();\n};\n\nexport const getGitPath = async () => {\n const { stdout: gitPath } = await asyncSpawn('git', ['rev-parse', '--show-toplevel'], { print: false });\n return gitPath.trim();\n};\n\nexport const getChangesOfFile = async (filePath: string) => {\n const { stdout: changes } = await asyncSpawn('git', ['diff', 'origin/master..', filePath], { print: false });\n return changes;\n};\n\nexport const isPathIgnored = async (path: string) => {\n try {\n await asyncSpawn('git', ['check-ignore', path], { print: false });\n return true;\n } catch {\n return false;\n }\n};\n","import { confirm, input, select } from '@inquirer/prompts';\nimport type { Prompt } from '@inquirer/type';\nimport { getGitPath } from './git.js';\nimport { SUPPORTED_CLUSTERS, endWithError } from './index.js';\nimport { sep } from 'path';\n\ndeclare global {\n interface SymbolConstructor {\n /** A method that is used to release resources held by an object. Called by the semantics of the `using` statement. */\n readonly dispose: unique symbol;\n /** A method that is used to asynchronously release resources held by an object. Called by the semantics of the `await using` statement. */\n readonly asyncDispose: unique symbol;\n }\n}\n// @ts-expect-error polyfill for node < 18.18\nSymbol.dispose ??= Symbol.for('nodejs.dispose');\n// @ts-expect-error polyfill for node < 18.18\nSymbol.asyncDispose ??= Symbol.for('nodejs.asyncDispose');\nlet cancelFn: (() => void) | undefined;\nconst handler = () => cancelFn?.();\nfunction addExitListener() {\n process.once('beforeExit', handler);\n return {\n [Symbol.dispose]() {\n process.off('beforeExit', handler);\n cancelFn = undefined;\n },\n };\n}\n\nasync function inquirerWrapper<Value, Config>(fn: Prompt<Value, Config>, ...params: Parameters<Prompt<Value, Config>>) {\n try {\n using _ = addExitListener();\n const result = fn(...params);\n cancelFn = result.cancel;\n return await result;\n } catch (error) {\n if (error instanceof Error && ['CancelPromptError', 'ExitPromptError'].includes(error.constructor.name)) {\n endWithError('Cancelled! 👋');\n }\n endWithError(error as Error);\n }\n}\n\nexport function safeSelect<Value>(...params: Parameters<typeof select<Value>>) {\n return inquirerWrapper(select, ...params);\n}\n\nconst splitWordAtCapital = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).split(/(?=[A-Z])/).join(' ');\n\nfunction getEnvironment() {\n return safeSelect({\n message: 'Which environment do you want to use?',\n choices: SUPPORTED_CLUSTERS.map(cluster => ({ name: splitWordAtCapital(cluster), value: cluster })),\n default: 'expManager',\n });\n}\n\nasync function getServiceName() {\n const currentServicePath = await getGitPath();\n const defaultValue = currentServicePath.split(sep).pop();\n return inquirerWrapper(input, { message: 'Enter the service name:', default: defaultValue });\n}\n\nexport function getVariationId(defaultVal = 'default') {\n return inquirerWrapper(input, { message: 'Enter your simulator id (Press enter to pass):', default: defaultVal });\n}\n\nasync function getPort(defaultVal = '8080', isLocal = false) {\n return inquirerWrapper(input, {\n message: `Enter the ${isLocal ? 'local ' : ''}port:`,\n default: defaultVal,\n validate(value) {\n // Regex source: https://stackoverflow.com/a/12968117\n if (!/^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/.test(value)) {\n return 'Please enter a valid port number';\n }\n return true;\n },\n });\n}\n\nexport async function getLocalPort(defaultVal = '5432') {\n return getPort(defaultVal, true);\n}\n\nconst VALUE_GETTER_MAP = {\n cluster: getEnvironment,\n variationId: getVariationId,\n service: getServiceName,\n port: (defaultVal = '8080') => getPort(defaultVal),\n 'local-port': getLocalPort,\n} as const;\n\nexport async function fillMissingRequiredValues<T extends { [key in keyof typeof VALUE_GETTER_MAP]?: string }>(values: T, requiredValues: (keyof T | { option: keyof T; defaultVal: string })[]) {\n for (const value of requiredValues) {\n const option = typeof value === 'object' ? value.option : value;\n const defaultVal = typeof value === 'object' ? value.defaultVal : undefined;\n if (typeof option !== 'string') {\n throw new Error(`Invalid option ${String(option)}`);\n }\n const getter = VALUE_GETTER_MAP[option as keyof typeof VALUE_GETTER_MAP];\n if (!getter) {\n throw new Error(`No value getter for ${String(option)}`);\n }\n\n values[option] ??= await getter(defaultVal) as T[keyof T & string];\n }\n return values;\n}\n\nexport async function promptForConfirmation(message: string, defaultVal = true) {\n return inquirerWrapper(confirm, { message, default: defaultVal });\n}\n","#!/usr/bin/env node\nimport fs from 'node:fs';\nimport asyncSpawn from './asyncSpawn.js';\nimport { promptForConfirmation } from './inquirer.js';\n\nconst IP_LINE_SUFFIX = 'SERVICE_HOST';\nconst PROD_CLUSTER_TO_CMD_MAP = {\n prodUs: ['us-autofleet-production', 'us-central1', 'autofleet-production'],\n prodEu: ['autofleetprod', 'europe-west1', 'autofleetprod'],\n prodJp: ['jp-autofleet-production', 'asia-northeast1', 'autofleet-japan'],\n};\nconst SIMULATION_CLUSTER_TO_CMD_MAP = {\n dev1: ['dev-cluster-2', 'europe-west1', 'dev1-experiment-manager'],\n e2eManager: ['e2e-cluster-2', 'europe-west1', 'e2e-project-1'],\n expManager: ['af-experiment-manager', 'europe-west1'],\n};\nconst STAGING_CLUSTER_TO_CMD_MAP = {\n staging: ['autofleet-staging', 'europe-west1-b'],\n loadTest: ['lt-autofleet-production', 'asia-northeast1', 'load-testing-428806'],\n};\nconst CLUSTER_TO_CMD_MAP = {\n ...PROD_CLUSTER_TO_CMD_MAP,\n ...SIMULATION_CLUSTER_TO_CMD_MAP,\n ...STAGING_CLUSTER_TO_CMD_MAP,\n};\n\nconst CLUSTER_TO_REDIS_REGION = {\n staging: 'europe-west1',\n};\n\nexport const SUPPORTED_CLUSTERS = Object.keys(CLUSTER_TO_CMD_MAP) as (keyof typeof CLUSTER_TO_CMD_MAP)[];\n\nconst getClusterDetails = async (clusterName: string) => {\n const command = CLUSTER_TO_CMD_MAP[clusterName as keyof typeof CLUSTER_TO_CMD_MAP];\n if (!command) {\n throw new Error(`Cluster name ${clusterName} does not exist!`);\n }\n const [name, region, project] = command;\n\n if (\n PROD_CLUSTER_TO_CMD_MAP[clusterName as keyof typeof PROD_CLUSTER_TO_CMD_MAP]\n && !(await promptForConfirmation(`❌❌ Are you sure you want to run this command on ${clusterName}? ❌❌`, false))) {\n console.log('Aborting...');\n return process.exit(1);\n }\n\n return { name, region, project };\n};\n\nexport const replaceInFile = ({ newFilePath, filePath, linesToReplace }: { newFilePath: string; filePath: string; linesToReplace: { find: string; replace: string }[] }) => {\n let fileAsString = fs.readFileSync(filePath, 'utf8');\n for (const { find, replace } of linesToReplace) {\n fileAsString = fileAsString.replace(find, replace);\n }\n fs.writeFileSync(newFilePath, fileAsString);\n};\nexport async function getCurrentCluster() {\n try {\n const { stdout } = await asyncSpawn('kubectl', ['config', 'current-context'], { print: false });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\nexport const connectToCluster = async (clusterName: string) => {\n const { name, region, project } = await getClusterDetails(clusterName);\n\n const expectedContext = `gke_${project || name}_${region}_${name}`;\n const currentContext = await getCurrentCluster();\n if (currentContext === expectedContext) {\n console.log(`Already connected to ${clusterName}, skipping connection to cluster...`);\n return { name, region, project };\n }\n\n await asyncSpawn('gcloud', ['container', 'clusters', 'get-credentials', name, '--region', region, '--project', project || name], { print: false });\n\n console.log(`Switched to ${clusterName} successfully`);\n\n return { name, region, project };\n};\nexport async function getCurrentNamespace() {\n try {\n const { stdout } = await asyncSpawn('kubectl', ['config', 'view', '--minify', '--output', 'jsonpath={..namespace}'], { print: false });\n return stdout.trim();\n } catch {\n return 'default'; // If no namespace is set, it defaults to 'default'\n }\n}\nexport const connectAndGetPrefix = async ({ clusterName, variationId }: { clusterName: string; variationId: string }) => {\n await connectToCluster(clusterName);\n return `--namespace=${variationId}`;\n};\nexport const parseIps = (ips: string) => {\n const ipLines = ips.split('\\n').filter(Boolean);\n ipLines.shift();\n\n let formattedIps = ipLines.map((ipLine) => {\n const [name, _type, _clusterIp, externalIp, _port, _age] = ipLine.split(/(\\s+)/).map(s => s.trim()).filter(Boolean);\n const serviceName = name.replace(/-/g, '_').toUpperCase();\n const formattedLine = `${serviceName}_${IP_LINE_SUFFIX}=${externalIp}`;\n return formattedLine;\n });\n formattedIps = formattedIps.filter(formattedIp => !formattedIp.includes('none') && !formattedIp.includes('undefined'));\n return formattedIps;\n};\n\nexport const endWithError = (error: string | Error, helpText?: string): never => {\n if (!(error instanceof Error)) {\n error = new Error(error);\n }\n console.error(error);\n if (helpText) {\n console.log(helpText);\n }\n return process.exit(1);\n};\n\nexport const isSimulationCluster = (clusterName: string) => Object.keys(SIMULATION_CLUSTER_TO_CMD_MAP).includes(clusterName);\n\nexport const getRedisRegion = (clusterName: string) => CLUSTER_TO_REDIS_REGION[clusterName as keyof typeof CLUSTER_TO_REDIS_REGION]\n || CLUSTER_TO_CMD_MAP[clusterName as keyof typeof CLUSTER_TO_CMD_MAP][1];\n"],"mappings":"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","names":["nativeParseArgs","package_default","GLOBAL_OPTIONS","parseArgs","params","data","nativeParseArgs","values","package_default","commands","command","example","longestDescriptionLength","description","help","option","type","short","spawn","createDeferredPromise","reject","resolve","res","rej","asyncSpawn_default","command","args","print","env","signal","shell","stubError","callerStack","promise","reject","resolve","createDeferredPromise","child","spawn","stdout","stderr","data","completionEventName","errorListener","error","completionListener","code","result","argumentString","getCurrentBranch","currentBranch","asyncSpawn_default","getGitPath","gitPath","getChangesOfFile","filePath","changes","isPathIgnored","path","confirm","input","select","fs","IP_LINE_SUFFIX","PROD_CLUSTER_TO_CMD_MAP","SIMULATION_CLUSTER_TO_CMD_MAP","STAGING_CLUSTER_TO_CMD_MAP","CLUSTER_TO_CMD_MAP","CLUSTER_TO_REDIS_REGION","SUPPORTED_CLUSTERS","getClusterDetails","clusterName","command","name","region","project","promptForConfirmation","replaceInFile","newFilePath","filePath","linesToReplace","fileAsString","fs","find","replace","getCurrentCluster","stdout","asyncSpawn_default","connectToCluster","expectedContext","getCurrentNamespace","connectAndGetPrefix","variationId","parseIps","ips","ipLines","formattedIps","ipLine","_type","_clusterIp","externalIp","_port","_age","s","formattedIp","endWithError","error","helpText","isSimulationCluster","getRedisRegion","sep","cancelFn","handler","addExitListener","inquirerWrapper","fn","params","_stack","_","__using","result","_error","_hasError","__callDispose","error","endWithError","safeSelect","select","splitWordAtCapital","str","getEnvironment","SUPPORTED_CLUSTERS","cluster","getServiceName","defaultValue","getGitPath","sep","input","getVariationId","defaultVal","getPort","isLocal","value","getLocalPort","VALUE_GETTER_MAP","fillMissingRequiredValues","values","requiredValues","option","getter","promptForConfirmation","message","confirm"]}