@coalescesoftware/coa 1.0.156 → 1.0.157
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.
- package/package.json +1 -1
- package/src/index.tsx +556 -0
package/package.json
CHANGED
package/src/index.tsx
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
/* eslint-disable multiline-comment-style */
|
|
3
|
+
|
|
4
|
+
import * as Deploy from "./Deploy"
|
|
5
|
+
import * as Plan from "./Plan"
|
|
6
|
+
import * as Refresh from "./Refresh"
|
|
7
|
+
import * as Package from "./Package"
|
|
8
|
+
import * as Shared from "@coalescesoftware/shared"
|
|
9
|
+
import * as CLIProfile from "./CLIProfile"
|
|
10
|
+
import * as RunOutput from './RunOutput'
|
|
11
|
+
import Chalk from "chalk"
|
|
12
|
+
import { Command } from "commander"
|
|
13
|
+
import * as CommonCLI from './CommonCLI'
|
|
14
|
+
import fs from "fs"
|
|
15
|
+
import inquirer from "inquirer"
|
|
16
|
+
|
|
17
|
+
// setting this needs to be first!
|
|
18
|
+
Shared.Logging.SetHTTPTransportOptions(Shared.Logging.EHttpServices.CLI)
|
|
19
|
+
const LogCLI = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI)
|
|
20
|
+
const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL)
|
|
21
|
+
|
|
22
|
+
const ChalkLogger = {
|
|
23
|
+
error: (message: string) => LogCLI.error(Chalk.redBright(message)),
|
|
24
|
+
green: (message: string) => LogCLI.info(Chalk.green(message)),
|
|
25
|
+
white: (message: string) => LogCLI.info(Chalk.whiteBright(message)),
|
|
26
|
+
blue: (message: string) => LogCLI.info(Chalk.blueBright(message)),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const program = new Command()
|
|
30
|
+
program.version(require("../package.json").version, "-v, --version")
|
|
31
|
+
program.option("-b, --debug", "Output extra debugging", false)
|
|
32
|
+
program.option("--config <coa-config-location>", "coa config file location")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
const AddOverridesToCommand = (command)=> {
|
|
36
|
+
Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
|
|
37
|
+
command.option(`--${key} <value>`, CLIProfile.ICLIProfileExample[key], "")
|
|
38
|
+
})
|
|
39
|
+
return command
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//computeCLIOverrides returns an object that has a value if any of them have been specified at the command line
|
|
43
|
+
//this is used as the final override when getting a CLIConfig
|
|
44
|
+
const ComputeCLIOverrides = (command):Partial<CLIProfile.ICLIProfile> => {
|
|
45
|
+
let overrides = {}
|
|
46
|
+
Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
|
|
47
|
+
const source = command.getOptionValueSource(key)
|
|
48
|
+
if (source == "cli") {
|
|
49
|
+
overrides[key] = command.getOptionValue(key)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
})
|
|
53
|
+
return overrides
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Default command (i.e., `coa` by itself) routes to help
|
|
57
|
+
*/
|
|
58
|
+
program.command("none", { hidden: true, isDefault: true })
|
|
59
|
+
.action(() => {
|
|
60
|
+
program.help()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Plan command is responsible for reading files and creating a Coalesce Deployment Plan
|
|
66
|
+
*/
|
|
67
|
+
AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
|
|
68
|
+
.option("-d, --dir <dir>", "Coalesce pipeline Yaml file path", ".")
|
|
69
|
+
.option("--out <plan-location>", "Coalesce plan location", "./coa-plan.json")
|
|
70
|
+
.description("plan a Coalesce deployment")
|
|
71
|
+
.action((options,cmd) => {
|
|
72
|
+
const cliOverrides = ComputeCLIOverrides(cmd)
|
|
73
|
+
|
|
74
|
+
const optsWithGlobals = cmd.optsWithGlobals()
|
|
75
|
+
const directoryPath = optsWithGlobals.dir
|
|
76
|
+
let logContextToUse: Shared.Logging.LogContext
|
|
77
|
+
|
|
78
|
+
// try {
|
|
79
|
+
// Shared.CLIOperations.VerifyAllPlanItems(config, token)
|
|
80
|
+
// } catch (error) {
|
|
81
|
+
// LogCLI.error(Chalk.redBright(`Error with required option values: ${error}`))
|
|
82
|
+
// Shared.CLIOperations.ExitCLISafe(1)
|
|
83
|
+
// }
|
|
84
|
+
|
|
85
|
+
LogCLI.info(Chalk.whiteBright(`Pipeline: ${Chalk.green("running")}...`))
|
|
86
|
+
|
|
87
|
+
const debugMode = optsWithGlobals.debug
|
|
88
|
+
if (!debugMode) {
|
|
89
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let config;
|
|
93
|
+
return Promise.resolve().then(()=> {
|
|
94
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
95
|
+
})
|
|
96
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
97
|
+
config = configResult
|
|
98
|
+
|
|
99
|
+
if (config.runtimeParameters) {
|
|
100
|
+
CommonCLI.ValidateRuntimeParameters(config.runtimeParameters)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined)
|
|
104
|
+
})
|
|
105
|
+
.then(({ teamInfo, firebase }: Shared.ConnectionOperations.ITeamInfoAndFirebase) => {
|
|
106
|
+
const firestore = firebase.firestore()
|
|
107
|
+
Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
|
|
108
|
+
const teamID =teamInfo.fbTeamID
|
|
109
|
+
const environmentID = config.runDetails.environmentID
|
|
110
|
+
|
|
111
|
+
return Shared.SchedulerOperations.GetRuntimeParametersObjectForRun(
|
|
112
|
+
firestore,
|
|
113
|
+
teamID,
|
|
114
|
+
environmentID,
|
|
115
|
+
config.runtimeParameters)
|
|
116
|
+
})
|
|
117
|
+
.then((runtimeParametersObject:Shared.Runner.TRunTimeParametersObjectType) => {
|
|
118
|
+
const envID = config.runDetails.environmentID
|
|
119
|
+
|
|
120
|
+
return Plan.CreatePlan(
|
|
121
|
+
directoryPath,
|
|
122
|
+
envID,
|
|
123
|
+
config.token,
|
|
124
|
+
`Deploy to environment: ${envID}`,
|
|
125
|
+
JSON.stringify(runtimeParametersObject)
|
|
126
|
+
)
|
|
127
|
+
}).then(result => {
|
|
128
|
+
const { plan, logContext } = result
|
|
129
|
+
logContextToUse = logContext
|
|
130
|
+
fs.writeFile(optsWithGlobals.out, JSON.stringify(plan), "utf8", (error) => {
|
|
131
|
+
if (error) {
|
|
132
|
+
LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred while saving plan ${error}`))
|
|
133
|
+
|
|
134
|
+
return `Plan incomplete and not saved to local file.`
|
|
135
|
+
} else {
|
|
136
|
+
LogCLI.infoContext(logContextToUse, Chalk.blueBright(`Plan complete and saved to local file: coa-plan.json`))
|
|
137
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}).catch(error => {
|
|
141
|
+
LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred while creating plan ${error}`))
|
|
142
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Deploy command is responsible for taking an already generated plan, and executing it
|
|
148
|
+
*/
|
|
149
|
+
AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
|
|
150
|
+
.option("-p, --plan <plan-location>", "Coalesce plan location", "./coa-plan.json")
|
|
151
|
+
.option("-o, --out <output json>", "Run Results Output in Json ")
|
|
152
|
+
.description("run a coalesce deployment plan")
|
|
153
|
+
.action((options,cmd) => {
|
|
154
|
+
const cliOverrides = ComputeCLIOverrides(cmd)
|
|
155
|
+
|
|
156
|
+
const optsWithGlobals = cmd.optsWithGlobals()
|
|
157
|
+
const plan = JSON.parse(fs.readFileSync(optsWithGlobals.plan, { encoding: "utf-8" }))
|
|
158
|
+
// const config = JSON.parse(fs.readFileSync(cmd.config, { encoding: "utf-8" }))
|
|
159
|
+
// const token = fs.readFileSync(cmd.token, { encoding: "utf-8" })
|
|
160
|
+
|
|
161
|
+
// try {
|
|
162
|
+
// Shared.CLIOperations.VerifyAllDeployItems(plan, config, token)
|
|
163
|
+
// } catch (error) {
|
|
164
|
+
// LogCLI.error(Chalk.redBright(`Error with required option values: ${error}`))
|
|
165
|
+
// Shared.CLIOperations.ExitCLISafe(1)
|
|
166
|
+
// }
|
|
167
|
+
|
|
168
|
+
const debugMode = optsWithGlobals.debug
|
|
169
|
+
if (!debugMode) {
|
|
170
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let logContextToUse: Shared.Logging.LogContext
|
|
174
|
+
let runInfo:Shared.Runner.IRunInfo
|
|
175
|
+
|
|
176
|
+
let config;
|
|
177
|
+
return Promise.resolve().then(()=> {
|
|
178
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
179
|
+
})
|
|
180
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
181
|
+
config = configResult
|
|
182
|
+
|
|
183
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(
|
|
184
|
+
config.token,
|
|
185
|
+
undefined,
|
|
186
|
+
)
|
|
187
|
+
}).then(({ teamInfo }: Shared.ConnectionOperations.ITeamInfoAndFirebase) => {
|
|
188
|
+
Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
|
|
189
|
+
|
|
190
|
+
runInfo = {
|
|
191
|
+
runType: Shared.Runner.ERunType.deploy,
|
|
192
|
+
runStatus: Shared.Runner.ERunStatus.running,
|
|
193
|
+
runDetails: {
|
|
194
|
+
environmentID: config.runDetails.environmentID
|
|
195
|
+
},
|
|
196
|
+
userCredentials: config.userCredentials,
|
|
197
|
+
runTimeParameters: plan.runtimeParameters || {},
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
Shared.Common.assert(Shared.Logging.LoggingArea.CLI,
|
|
201
|
+
!!runInfo, "runinfo must exist to continue")
|
|
202
|
+
return Deploy.DeployWithCLI(plan, runInfo, config.token)
|
|
203
|
+
.then((result) => {
|
|
204
|
+
const { runCounter, runCompletion, logContext } = result
|
|
205
|
+
logContextToUse = logContext ?? {}
|
|
206
|
+
LogCLI.infoContext(logContextToUse, Chalk.whiteBright(
|
|
207
|
+
`Job ${runCounter}: ${Chalk.green("running")}...`
|
|
208
|
+
))
|
|
209
|
+
|
|
210
|
+
return runCompletion.finally(()=> {
|
|
211
|
+
const outputFilePath = optsWithGlobals.out
|
|
212
|
+
CommonCLI.FinishWithOutputFile(
|
|
213
|
+
logContextToUse,
|
|
214
|
+
outputFilePath,
|
|
215
|
+
runCounter,
|
|
216
|
+
config.token
|
|
217
|
+
)
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
.then(() => {
|
|
221
|
+
LogCLI.infoContext(logContextToUse, "Deployment successful!")
|
|
222
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
223
|
+
})
|
|
224
|
+
}).catch(error => {
|
|
225
|
+
LogCLI.errorContext(logContextToUse, Chalk.redBright(`An error occurred during deployment ${error.toString()}`))
|
|
226
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Refresh command begins a locally executed Coalesce Environment Run
|
|
232
|
+
*/
|
|
233
|
+
AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh))
|
|
234
|
+
.description("runs a Coalesce pipeline")
|
|
235
|
+
.option("-o, --out <output json>", "Run Results Output in Json ")
|
|
236
|
+
.action(( options, command) => {
|
|
237
|
+
const cliOverrides = ComputeCLIOverrides(command)
|
|
238
|
+
const optsWithGlobals = command.optsWithGlobals()
|
|
239
|
+
const debugMode = optsWithGlobals.debug
|
|
240
|
+
if (!debugMode) {
|
|
241
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
let logContextToUse
|
|
247
|
+
|
|
248
|
+
//TODO:
|
|
249
|
+
//FROM MICHAEL:
|
|
250
|
+
//WHY DO WE HAVE THIS CONFIG?
|
|
251
|
+
let runInfo:Shared.Runner.IRunInfo
|
|
252
|
+
let config;
|
|
253
|
+
return Promise.resolve().then(()=> {
|
|
254
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
255
|
+
})
|
|
256
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
257
|
+
config = configResult
|
|
258
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined)
|
|
259
|
+
})
|
|
260
|
+
.then(({ teamInfo, firebase }) => {
|
|
261
|
+
const firestore = firebase.firestore()
|
|
262
|
+
Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID })
|
|
263
|
+
const teamID = teamInfo.fbTeamID
|
|
264
|
+
const environmentID = config.runDetails.environmentID
|
|
265
|
+
return Shared.SchedulerOperations.GetRuntimeParametersObjectForRun(firestore,
|
|
266
|
+
teamID, environmentID, config.runtimeParameters)
|
|
267
|
+
})
|
|
268
|
+
.then((runtimeParametersObject:Shared.Runner.TRunTimeParametersObjectType) => {
|
|
269
|
+
runInfo = {
|
|
270
|
+
runType: Shared.Runner.ERunType.refresh,
|
|
271
|
+
runStatus: Shared.Runner.ERunStatus.running,
|
|
272
|
+
runDetails: {
|
|
273
|
+
environmentID: config.runDetails.environmentID,
|
|
274
|
+
jobID: config.runDetails.jobID,
|
|
275
|
+
includeNodesSelector: config.runDetails.includeNodesSelector,
|
|
276
|
+
excludeNodesSelector: config.runDetails.excludeNodesSelector
|
|
277
|
+
},
|
|
278
|
+
userCredentials:config.userCredentials,
|
|
279
|
+
runTimeParameters: runtimeParametersObject,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
Shared.Common.CleanupUndefinedValuesFromObject(runInfo)
|
|
283
|
+
|
|
284
|
+
LogCLIInternal.infoContext(logContextToUse, "cliOverrides", cliOverrides)
|
|
285
|
+
//LogCLIInternal.infoContext(logContextToUse, "got the cli config", config)
|
|
286
|
+
//LogCLIInternal.infoContext(logContextToUse, "got the run info", config)
|
|
287
|
+
Shared.Common.assert(Shared.Logging.LoggingArea.CLI,
|
|
288
|
+
!!runInfo, "runinfo must exist to continue")
|
|
289
|
+
return Refresh.RefreshWithCLI(config.token, runInfo)
|
|
290
|
+
.then((result) => {
|
|
291
|
+
const { runCounter, runCompletion, logContext } = result
|
|
292
|
+
logContextToUse = logContext ?? {}
|
|
293
|
+
LogCLI.infoContext(logContextToUse, Chalk.whiteBright(`Refresh run initialized. RunCounter: ${runCounter}`))
|
|
294
|
+
|
|
295
|
+
return runCompletion.finally(() => {
|
|
296
|
+
const outputFilePath = optsWithGlobals.out
|
|
297
|
+
CommonCLI.FinishWithOutputFile(
|
|
298
|
+
logContextToUse,
|
|
299
|
+
outputFilePath,
|
|
300
|
+
runCounter,
|
|
301
|
+
config.token
|
|
302
|
+
)
|
|
303
|
+
}).then(() => {
|
|
304
|
+
LogCLI.infoContext(logContextToUse, "Refresh successful!")
|
|
305
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
306
|
+
})
|
|
307
|
+
})
|
|
308
|
+
}).catch(error => {
|
|
309
|
+
LogCLI.errorContext(logContextToUse, Chalk.redBright("Error during refresh!: "), error)
|
|
310
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
311
|
+
})
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
//////////////////////////////////////
|
|
315
|
+
///// COA PACKAGES
|
|
316
|
+
//////////////////////////////////////
|
|
317
|
+
|
|
318
|
+
const PackageInit = program.command(Shared.CLIOperations.ECLICommands.Package)
|
|
319
|
+
.description("experimental feature")
|
|
320
|
+
// removing description until Lhotse 4.0 release
|
|
321
|
+
// .description(`\n--------------------------------------\n*** Experimental Feature ***\n--------------------------------------\nImport workspace information (aka Coalesce Package) from other Coalesce repositories into your the environment provided in your COA config, or --environmentID override.
|
|
322
|
+
// \nSubcommands:
|
|
323
|
+
// add <location> imports data from <location> (either URL with optional #commit, #branch, or file path)
|
|
324
|
+
// remove <packageID> removes imported package with <packageID> from your Coalesce project\n--------------------------------------\n`)
|
|
325
|
+
.option("--list [workspaceID]", "Lists installed package names for default or specified workspace")
|
|
326
|
+
// .command("none", { hidden: true, isDefault: true }) // removing description until Lhotse 4.0 release
|
|
327
|
+
.action((opts, cmd) => {
|
|
328
|
+
const cliOverrides = ComputeCLIOverrides(cmd)
|
|
329
|
+
const optsWithGlobals = cmd.optsWithGlobals()
|
|
330
|
+
const list = optsWithGlobals.list
|
|
331
|
+
const debugMode = optsWithGlobals.debug
|
|
332
|
+
|
|
333
|
+
if (!debugMode) {
|
|
334
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
let environmentID
|
|
338
|
+
|
|
339
|
+
if (list) {
|
|
340
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
341
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
342
|
+
// if list is a boolean, then --list had no workspaceID arg, so use workspaceID from coaConfig, else use provided workspaceID
|
|
343
|
+
environmentID = typeof list === "boolean" ? configResult.runDetails.environmentID : list
|
|
344
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(configResult.token, undefined)
|
|
345
|
+
})
|
|
346
|
+
.then((authInfo) => {
|
|
347
|
+
const packageContext = Package.InitializePackageContext(authInfo, environmentID)
|
|
348
|
+
|
|
349
|
+
return Package.GetPackageListMessageCLI(packageContext)
|
|
350
|
+
})
|
|
351
|
+
.then((packageListCLI) => {
|
|
352
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(Chalk.bgBlueBright(packageListCLI))
|
|
353
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
354
|
+
})
|
|
355
|
+
.catch((error) => {
|
|
356
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).error(Chalk.red(`CLI Package listing error`, error))
|
|
357
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
358
|
+
})
|
|
359
|
+
} else {
|
|
360
|
+
program.help()
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
// removing description until Lhotse 4.0 release - also todo: do this better anyway
|
|
365
|
+
// PackageInit.command("none", { hidden: true, isDefault: true })
|
|
366
|
+
// .action(() => {
|
|
367
|
+
// PackageInit.help()
|
|
368
|
+
// })
|
|
369
|
+
|
|
370
|
+
const throwForbiddenExperimentalError = () => {
|
|
371
|
+
const errorMessage = ` 403 - Forbidden: You do not have permission to access this experimental feature`
|
|
372
|
+
throw new Error(errorMessage)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const AddPackage = AddOverridesToCommand(PackageInit.command(`${Shared.CLIOperations.ECLICommands.Add} <location>`))
|
|
376
|
+
// .description("imports data from <location> (either URL with optional #commit or dir path) to your Coalesce project for given environment ID") // removing description until Lhotse 4.0 release
|
|
377
|
+
.option("-y", "Auto-confirm all overwrite prompts")
|
|
378
|
+
|
|
379
|
+
AddPackage
|
|
380
|
+
.action((location, options, cmd) => {
|
|
381
|
+
const cliOverrides = ComputeCLIOverrides(cmd)
|
|
382
|
+
const optsWithGlobals = cmd.optsWithGlobals()
|
|
383
|
+
const debugMode = optsWithGlobals.debug
|
|
384
|
+
const packageLocation: string = location
|
|
385
|
+
const confirmPrompts: boolean = options.y || false
|
|
386
|
+
|
|
387
|
+
if (!debugMode) {
|
|
388
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
ChalkLogger.green(`Initializing package installation...`)
|
|
392
|
+
|
|
393
|
+
let loggerContext
|
|
394
|
+
let token: string
|
|
395
|
+
let cliConfig: CLIProfile.ICLIConfig
|
|
396
|
+
let environmentID
|
|
397
|
+
let packageContext
|
|
398
|
+
let packageProvider
|
|
399
|
+
|
|
400
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
401
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
402
|
+
cliConfig = configResult
|
|
403
|
+
token = cliConfig.token
|
|
404
|
+
environmentID = cliConfig.runDetails.environmentID
|
|
405
|
+
|
|
406
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined)
|
|
407
|
+
})
|
|
408
|
+
.then((authInfo) => {
|
|
409
|
+
// this feature only available to SuperUsers until Lhotse release
|
|
410
|
+
if (!authInfo.teamInfo.fbHasSuperUserAccess) {
|
|
411
|
+
throwForbiddenExperimentalError()
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
packageContext = Package.InitializePackageContext(authInfo, environmentID)
|
|
415
|
+
packageProvider = new Package.PackageProvider(packageLocation, loggerContext)
|
|
416
|
+
|
|
417
|
+
// need to getWorkspaceDataFS here in order to get package ID from package provider
|
|
418
|
+
return packageProvider.getWorkspaceDataFS()
|
|
419
|
+
.then(() => Shared.Workspaces.getAllWorkspaceDataFromFirebase(authInfo.firebase.firestore(), authInfo.teamInfo.fbTeamID, environmentID))
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
.then(workspaceData => {
|
|
423
|
+
const isPackageAlreadyInstalled = Package.IsPackageAlreadyInstalled(workspaceData.packages || {}, packageProvider.id)
|
|
424
|
+
|
|
425
|
+
const install = () => {
|
|
426
|
+
return Package.InstallPackage(packageProvider, packageContext)
|
|
427
|
+
.then(() => {
|
|
428
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(Chalk.green(`CLI Package Installation complete`))
|
|
429
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
430
|
+
})
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (isPackageAlreadyInstalled) {
|
|
434
|
+
if (confirmPrompts) {
|
|
435
|
+
return install()
|
|
436
|
+
} else {
|
|
437
|
+
const promptData = [
|
|
438
|
+
{
|
|
439
|
+
name: "confirmOverwrite",
|
|
440
|
+
type: "confirm",
|
|
441
|
+
message: `Package "${packageProvider.id}" already exists. Continuing with installation will remove any changes you might have made and overwrite the data previously imported from this package.
|
|
442
|
+
\n\nWould you like to continue installation and overwrite any previously installed package data from "${packageProvider.id}"?`,
|
|
443
|
+
default: false
|
|
444
|
+
},
|
|
445
|
+
]
|
|
446
|
+
|
|
447
|
+
return inquirer.prompt(promptData)
|
|
448
|
+
.then(answers => {
|
|
449
|
+
const shouldOverwrite = answers.confirmOverwrite
|
|
450
|
+
|
|
451
|
+
if (shouldOverwrite) {
|
|
452
|
+
return install()
|
|
453
|
+
} else {
|
|
454
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(`CLI Package installation aborted`)
|
|
455
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
456
|
+
}
|
|
457
|
+
})
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
return install()
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
.catch(error => {
|
|
464
|
+
if (error.isTtyError) {
|
|
465
|
+
// Prompt couldn't be rendered in the current environment
|
|
466
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`There was a problem rendering the overwrite confirmation prompt in your environment. \n\n To overwrite package without prompts, add the -y param to the end of the command and try again.`, error))
|
|
467
|
+
}
|
|
468
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`CLI Package Installation error`, error))
|
|
469
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
470
|
+
})
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
const RemovePackage = AddOverridesToCommand(PackageInit.command(`${Shared.CLIOperations.ECLICommands.Remove} <id>`))
|
|
474
|
+
// .description("removes imported package with <id> from your Coalesce project for given environment ID") // removing description until Lhotse 4.0 release
|
|
475
|
+
.option("-y", "Auto-confirm all remove prompts")
|
|
476
|
+
|
|
477
|
+
RemovePackage
|
|
478
|
+
.action((id: string, options, cmd) => {
|
|
479
|
+
const cliOverrides = ComputeCLIOverrides(cmd)
|
|
480
|
+
const optsWithGlobals = cmd.optsWithGlobals()
|
|
481
|
+
const debugMode = optsWithGlobals.debug
|
|
482
|
+
const packageID: string = id.toUpperCase()
|
|
483
|
+
const confirmPrompts: boolean = options.y || false
|
|
484
|
+
|
|
485
|
+
if (!debugMode) {
|
|
486
|
+
Shared.CLIOperations.DisableNonCLIConsoleLogs()
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
ChalkLogger.green(`Initializing package removal...`)
|
|
490
|
+
|
|
491
|
+
let loggerContext: Shared.Logging.LogContext
|
|
492
|
+
let token: string
|
|
493
|
+
let cliConfig: CLIProfile.ICLIConfig
|
|
494
|
+
let environmentID: string | number
|
|
495
|
+
|
|
496
|
+
return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
|
|
497
|
+
.then((configResult: CLIProfile.ICLIConfig) => {
|
|
498
|
+
cliConfig = configResult
|
|
499
|
+
token = cliConfig.token
|
|
500
|
+
environmentID = cliConfig.runDetails.environmentID
|
|
501
|
+
|
|
502
|
+
return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined)
|
|
503
|
+
})
|
|
504
|
+
.then((authInfo) => {
|
|
505
|
+
// this feature only available to SuperUsers until Lhotse release
|
|
506
|
+
if (!authInfo.teamInfo.fbHasSuperUserAccess) {
|
|
507
|
+
throwForbiddenExperimentalError()
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const packageContext = Package.InitializePackageContext(authInfo, environmentID as number)
|
|
511
|
+
const uninstall = () => Package.UninstallPackage(packageID, packageContext)
|
|
512
|
+
.then(() => {
|
|
513
|
+
ChalkLogger.green("Package removal completed successfully!")
|
|
514
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
if (confirmPrompts) {
|
|
518
|
+
return uninstall()
|
|
519
|
+
} else {
|
|
520
|
+
const promptData = [
|
|
521
|
+
{
|
|
522
|
+
name: "confirmRemove",
|
|
523
|
+
type: "confirm",
|
|
524
|
+
message: `Removing a package will remove all imported data from that package, including any edits you have made on that imported data. \n\nAre you sure you'd like to remove package "${packageID}"?`,
|
|
525
|
+
default: false
|
|
526
|
+
},
|
|
527
|
+
]
|
|
528
|
+
return inquirer.prompt(promptData)
|
|
529
|
+
.then(answers => {
|
|
530
|
+
const shouldRemove = answers.confirmRemove
|
|
531
|
+
|
|
532
|
+
if (shouldRemove) {
|
|
533
|
+
return uninstall()
|
|
534
|
+
} else {
|
|
535
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).info(`CLI Package removal aborted`)
|
|
536
|
+
Shared.CLIOperations.ExitCLISafe(0)
|
|
537
|
+
}
|
|
538
|
+
})
|
|
539
|
+
}
|
|
540
|
+
})
|
|
541
|
+
.catch(error => {
|
|
542
|
+
if (error.isTtyError) {
|
|
543
|
+
// Prompt couldn't be rendered in the current environment
|
|
544
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`There was a problem rendering the removal confirmation prompt in your environment. \n\n To remove without prompts, add the -y param to the end of the command and try again.`, error))
|
|
545
|
+
}
|
|
546
|
+
Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI).errorContext(loggerContext, Chalk.red(`CLI Package removal error`, error))
|
|
547
|
+
Shared.CLIOperations.ExitCLISafe(1)
|
|
548
|
+
})
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Put new commands above.
|
|
553
|
+
* Don't delete the commands below; they're responsible for Commander reading and executing options.
|
|
554
|
+
*/
|
|
555
|
+
program.parse()
|
|
556
|
+
program.opts()
|