UNPKG

@facets-cloud/facetsctlv3

Version:
160 lines (159 loc) 7.75 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const FacetsApi = __importStar(require("../../services/facets-api")); const config_service_1 = require("../../services/config-service"); const errors_1 = require("@oclif/core/lib/errors"); class Wait extends core_1.Command { static description = 'Wait for the sync status of the specified apps, and trigger sync if --sync is provided'; static flags = { project: core_1.Flags.string({ char: 'p', description: 'Project name', required: true, }), environment: core_1.Flags.string({ char: 'e', description: 'Environment name', required: true, }), sync: core_1.Flags.boolean({ description: 'Trigger a sync if apps are out-of-sync', default: false, }), debug: core_1.Flags.boolean({ description: 'To check API response for each resource', default: false, hidden: true }) }; static args = { apps: core_1.Args.string({ name: 'apps', description: 'List of app names to wait for (comma-separated | example: ... sync app1,app2,app3 -p ...)', required: true, }) }; static usage = 'facetsctl release wait <apps> -p <value> -e <value> [--sync]'; async run() { const { flags, args } = await this.parse(Wait); const { project, environment, sync, debug } = flags; const apps = args.apps ? args?.apps?.split(',')?.map(app => app.trim()) : []; const allAppsSet = new Set(apps); const failedAppsSet = new Set(); const redText = (text) => `\x1b[31m${text}\x1b[0m`; const greenText = (text) => `\x1b[32m${text}\x1b[0m`; const blueText = (text) => `\x1b[34m${text}\x1b[0m`; const configFilePath = config_service_1.ConfigService.findConfigFile(); if (!configFilePath) { throw new errors_1.CLIError('Configuration file not found. Please ensure you are logged in.', { exit: 2 }); } const config = config_service_1.ConfigService.readConfig(configFilePath); this.log(`Logged in to: ${config.ControlPlaneURL} with user: ${config.Username}`); if (sync) { core_1.ux.action.start('Initiating sync process before starting to wait'); try { const syncResponse = await FacetsApi.syncApps(config.ControlPlaneURL, config.Username, config.AccessToken, project, environment, apps); const alreadyInSyncResources = []; syncResponse?.resourceStatuses?.forEach((resource) => { if (resource?.syncStatus === 'IN_SYNC') { alreadyInSyncResources.push(resource?.resourceName); allAppsSet.delete(resource?.resourceName); } }); if (alreadyInSyncResources?.length) { this.log(blueText(`Following resource(s) are already in sync: ${alreadyInSyncResources.join(', ')}.`)); } if (allAppsSet?.size) { this.log(`Starting syncing process for the following resource(s): ${(Array.from(allAppsSet))?.join(', ')}`); } } catch (error) { core_1.ux.action.stop('Failed'); if (error instanceof Error) { throw new errors_1.CLIError(`Failed to trigger sync: ${error.message}`, { exit: 2 }); } } } if (allAppsSet?.size) core_1.ux.action.start('Waiting for apps to sync'); const timeout = 15 * 60 * 1000; let elapsedTime = 0; let releaseFailed = false; while (elapsedTime < timeout) { try { const statusResponse = await FacetsApi.checkAppStatus(config.ControlPlaneURL, config.Username, config.AccessToken, project, environment, apps); if (debug) { console.log(`WAIT RSP (${elapsedTime})=> `, statusResponse); } statusResponse?.resourceStatuses?.forEach((resource) => { if (resource.syncStatus === 'IN_SYNC' && allAppsSet?.has(resource.resourceName)) { this.log(` - ${resource.resourceName} has synced successfully.`); allAppsSet?.delete(resource.resourceName); } else if (resource.releaseStatus === 'FAILED') { releaseFailed = true; if (sync) { allAppsSet?.clear(); } else { this.log(` - ${resource.resourceName} could not be synced due to release failure.`); failedAppsSet.add(resource?.resourceName); allAppsSet?.delete(resource.resourceName); } } }); if (allAppsSet?.size === 0) { core_1.ux.action.stop((releaseFailed && sync) ? redText('unsuccessful due to release failure.') : ((releaseFailed && !sync) ? redText('completed') : greenText('completed.'))); if (releaseFailed && sync) { throw new errors_1.CLIError('All apps could not be synced', { exit: 2 }); } else if (!sync && failedAppsSet?.size > 0 && failedAppsSet?.size < apps?.length) { throw new errors_1.CLIError(`${Array.from(failedAppsSet)?.join(', ')} could not be synced`, { exit: 2 }); } break; } if (failedAppsSet?.size == apps?.length) { throw new errors_1.CLIError('All apps have reached FAILED release state', { exit: 2 }); } await new Promise((resolve) => setTimeout(resolve, 5000)); elapsedTime += 5000; } catch (error) { core_1.ux.action.stop('Failed'); if (error instanceof Error) { throw new errors_1.CLIError(`Error while checking app status: ${error.message}`, { exit: 2 }); } return; } } if (allAppsSet?.size) { this.log(`Timed out waiting for apps to become in-sync.`); throw new errors_1.CLIError(`Apps which are still out of sync: ${Array.from(allAppsSet)?.join(', ')}`, { exit: 124 }); } } } exports.default = Wait;