@coalescesoftware/coa 1.0.101 → 1.0.113

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/bin/CLIProfile.js CHANGED
@@ -19,20 +19,37 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
19
  return result;
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.GetCLIConfig = exports.ICLIProfileExample = void 0;
22
+ exports.GetCLIConfig = exports.ICLIProfileExample = exports.GetDefaultLocationForCoaConfigFile = void 0;
23
23
  /* eslint-disable multiline-comment-style */
24
24
  const Shared = __importStar(require("@coalescesoftware/shared"));
25
+ const immer = __importStar(require("immer"));
25
26
  const os = require('os');
26
27
  const path = require('path');
27
28
  const ini = require('ini');
28
29
  const fs = require('fs');
30
+ const RemoveCredentialsFromCLIProfile = (cliProfile) => {
31
+ return immer.produce(cliProfile, (draft) => {
32
+ if (draft.snowflakePassword)
33
+ draft.snowflakePassword = '<REDACTED>';
34
+ if (draft.snowflakeAccount)
35
+ draft.snowflakeAccount = '<REDACTED>';
36
+ });
37
+ };
38
+ const RemoveCredentialsFromCLIProfiles = (cliProfiles) => {
39
+ return immer.produce(cliProfiles, (draftState) => {
40
+ Object.keys(draftState).forEach((cliProfileName) => {
41
+ draftState[cliProfileName] = RemoveCredentialsFromCLIProfile(cliProfiles[cliProfileName]);
42
+ });
43
+ });
44
+ };
29
45
  const CLILogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL);
30
- const getDefaultLocationForCoaConfigFile = () => {
46
+ const GetDefaultLocationForCoaConfigFile = () => {
31
47
  const homedir = os.homedir();
32
48
  const coaConfigLocation = path.join(homedir, ".coa/config");
33
49
  CLILogger.info("using default location", coaConfigLocation);
34
50
  return coaConfigLocation;
35
51
  };
52
+ exports.GetDefaultLocationForCoaConfigFile = GetDefaultLocationForCoaConfigFile;
36
53
  //voodoo typescript magic in order to get runtime and compiletime ICLIProfile code
37
54
  //https://stackoverflow.com/questions/45670705/iterate-over-interface-properties-in-typescript
38
55
  exports.ICLIProfileExample = {
@@ -45,9 +62,12 @@ exports.ICLIProfileExample = {
45
62
  snowflakeRole: "Snowflake Role",
46
63
  snowflakeUsername: "Snowflake Username",
47
64
  snowflakeWarehouse: "Snowflake Warehouse",
48
- token: "Coalesce Token"
65
+ token: "Coalesce Token",
66
+ jobID: "Coalesce JobID",
67
+ include: "Coalesce Node Selector",
68
+ exclude: "Coalesce Node Selector"
49
69
  };
50
- const readCLIProfiles = (filePath) => {
70
+ const ReadCLIProfiles = (filePath) => {
51
71
  return fs.promises.readFile(filePath, 'utf-8').then((file) => {
52
72
  return ini.parse(file);
53
73
  }).catch((err) => {
@@ -55,10 +75,9 @@ const readCLIProfiles = (filePath) => {
55
75
  throw new Error("unable to read cli profile");
56
76
  });
57
77
  };
58
- const getFinalCLIProfile = (commandLineOverrides) => {
78
+ const GetFinalCLIProfile = (commandLineOverrides, configFileLocation) => {
59
79
  let profileToUseOverride = commandLineOverrides.profile ? commandLineOverrides.profile : null;
60
- const defaultPath = getDefaultLocationForCoaConfigFile();
61
- return readCLIProfiles(defaultPath).then((cliProfiles) => {
80
+ return ReadCLIProfiles(configFileLocation).then((cliProfiles) => {
62
81
  return cliProfiles;
63
82
  }).catch((err) => {
64
83
  //unable to read cli profiles
@@ -74,7 +93,7 @@ const getFinalCLIProfile = (commandLineOverrides) => {
74
93
  const profileToUse = profileToUseOverride || //cli override
75
94
  (!!defaultCLIProfile && defaultCLIProfile.profile) //default profile exists
76
95
  || "";
77
- CLILogger.info("using profile", profileToUse, "cliProfiles", JSON.stringify(cliProfiles));
96
+ CLILogger.info("using profile", profileToUse, "cliProfiles", JSON.stringify(RemoveCredentialsFromCLIProfiles(cliProfiles)));
78
97
  if (profileToUse) {
79
98
  if (!(profileToUse in cliProfiles)) {
80
99
  throw new Error(`unable to find profile ${profileToUse}`);
@@ -86,13 +105,16 @@ const getFinalCLIProfile = (commandLineOverrides) => {
86
105
  return finalCLIProfile;
87
106
  });
88
107
  };
89
- const GetCLIConfig = (commandLineOverrides) => {
90
- return getFinalCLIProfile(commandLineOverrides).then((cliProfile) => {
91
- CLILogger.info("got final cli profile", JSON.stringify(cliProfile));
92
- return {
108
+ const GetCLIConfig = (commandLineOverrides, configFileLocation) => {
109
+ return GetFinalCLIProfile(commandLineOverrides, configFileLocation).then((cliProfile) => {
110
+ CLILogger.info("got final cli profile configFileLocation:", configFileLocation, JSON.stringify(RemoveCredentialsFromCLIProfile(cliProfile)));
111
+ const cliConfig = {
93
112
  token: cliProfile.token,
94
113
  runDetails: {
95
- environmentID: cliProfile.environmentID
114
+ environmentID: cliProfile.environmentID,
115
+ jobID: cliProfile.jobID,
116
+ includeNodesSelector: cliProfile.include,
117
+ excludeNodesSelector: cliProfile.exclude
96
118
  },
97
119
  userCredentials: {
98
120
  snowflakeAccount: cliProfile.snowflakeAccount,
@@ -104,6 +126,8 @@ const GetCLIConfig = (commandLineOverrides) => {
104
126
  snowflakeWarehouse: cliProfile.snowflakeWarehouse
105
127
  }
106
128
  };
129
+ Shared.Common.CleanupUndefinedValuesFromObject(cliConfig);
130
+ return cliConfig;
107
131
  });
108
132
  };
109
133
  exports.GetCLIConfig = GetCLIConfig;
package/bin/CommonCLI.js CHANGED
@@ -19,11 +19,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
19
  return result;
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
22
+ exports.FinishWithOutputFile = exports.GetUserConnectionForCLI = exports.CleanupCLIJob = void 0;
23
23
  const Shared = __importStar(require("@coalescesoftware/shared"));
24
24
  const fs = __importStar(require("fs"));
25
25
  const crypto = __importStar(require("crypto"));
26
+ const RunOutput = __importStar(require("./RunOutput"));
26
27
  const RunnerBackendLogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.RunnerBackend);
28
+ const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_INTERNAL);
27
29
  const CleanupCLIJob = (runCompletion, firebase, logContext, action) => {
28
30
  const cleanupPromise = new Promise((resolve, reject) => {
29
31
  let promiseError = null;
@@ -104,4 +106,14 @@ const GetUserConnectionForCLI = (userID, runInfo) => {
104
106
  });
105
107
  };
106
108
  exports.GetUserConnectionForCLI = GetUserConnectionForCLI;
109
+ const FinishWithOutputFile = (logContextToUse, outputFilePath, runCounter, token) => {
110
+ if (!outputFilePath) {
111
+ return Promise.resolve();
112
+ }
113
+ else {
114
+ LogCLIInternal.infoContext(logContextToUse, "saving run results to file", outputFilePath);
115
+ return RunOutput.SaveRunOutputToFile(outputFilePath, runCounter.toString(), token);
116
+ }
117
+ };
118
+ exports.FinishWithOutputFile = FinishWithOutputFile;
107
119
  //# sourceMappingURL=CommonCLI.js.map
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.SaveRunOutputToFile = void 0;
23
+ const Shared = __importStar(require("@coalescesoftware/shared"));
24
+ const CLILogger = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI);
25
+ const cleanRunResult = (nodeID, runResult) => {
26
+ return {
27
+ nodeID,
28
+ queryResultSequence: runResult.queryResultSequence
29
+ };
30
+ };
31
+ const GetRunOutputForRunCounter = (firestore, teamID, runID) => {
32
+ let runData;
33
+ return Shared.Runs.getRun(firestore, teamID, runID).get()
34
+ .then((runDataResult /*query snapshot*/) => {
35
+ if (!runDataResult.docs.length) {
36
+ const errorMessage = `wasnt able to get exactly one run for runID ${runID}`;
37
+ CLILogger.emergContext({
38
+ orgID: teamID
39
+ }, errorMessage);
40
+ throw new Error(errorMessage);
41
+ }
42
+ const runInfo = runDataResult.docs[0].data();
43
+ runData = {
44
+ runResults: {
45
+ runStartTime: runInfo.runStartTime,
46
+ runEndTime: runInfo.runEndTime,
47
+ runType: runInfo.runType,
48
+ runStatus: runInfo.runStatus,
49
+ runID: runInfo.id,
50
+ runResults: []
51
+ }
52
+ };
53
+ return Shared.Runs.getRunRunResultsCollection(firestore, teamID, runID.toString())
54
+ .get().then((queryResult /*querySnapshot*/) => {
55
+ let runResults = {};
56
+ queryResult.docs.forEach((runResultDoc) => {
57
+ const stepCounter = runResultDoc.id;
58
+ const runResult = runResultDoc.data();
59
+ runResults[stepCounter] = cleanRunResult(stepCounter, runResult.history[0]);
60
+ });
61
+ runData.runResults.runResults = runInfo.runHistory.map((stepCounter) => {
62
+ return runResults[stepCounter];
63
+ });
64
+ });
65
+ }).then(() => {
66
+ return runData;
67
+ });
68
+ };
69
+ const SaveRunOutputToFile = (runOutputFileLocation, runIDString, token) => {
70
+ return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(token, undefined).then((authInfo) => {
71
+ const { teamInfo, firebase } = authInfo;
72
+ const teamID = teamInfo.fbTeamID;
73
+ const firestore = firebase.firestore();
74
+ const runID = parseInt(runIDString);
75
+ return GetRunOutputForRunCounter(firestore, teamID, runID);
76
+ }).then((runOutput) => {
77
+ const runOutputJSON = Shared.Common.StringifyFirestoreObject(runOutput);
78
+ return Shared.Common.WriteFile(runOutputFileLocation, runOutputJSON + "\n");
79
+ });
80
+ };
81
+ exports.SaveRunOutputToFile = SaveRunOutputToFile;
82
+ //# sourceMappingURL=RunOutput.js.map
package/bin/index.js CHANGED
@@ -31,6 +31,7 @@ const Shared = __importStar(require("@coalescesoftware/shared"));
31
31
  const CLIProfile = __importStar(require("./CLIProfile"));
32
32
  const chalk_1 = __importDefault(require("chalk"));
33
33
  const commander_1 = require("commander");
34
+ const CommonCLI = __importStar(require("./CommonCLI"));
34
35
  const fs_1 = __importDefault(require("fs"));
35
36
  // setting this needs to be first!
36
37
  Shared.Logging.SetHTTPTransportOptions(Shared.Logging.EHttpServices.CLI);
@@ -39,7 +40,8 @@ const LogCLIInternal = Shared.Logging.GetLogger(Shared.Logging.LoggingArea.CLI_I
39
40
  const program = new commander_1.Command();
40
41
  program.version(require("../package.json").version, "-v, --version");
41
42
  program.option("-b, --debug", "Output extra debugging", false);
42
- const addOverridesToCommand = (command) => {
43
+ program.option("--config <coa-config-location>", "coa config file location", CLIProfile.GetDefaultLocationForCoaConfigFile());
44
+ const AddOverridesToCommand = (command) => {
43
45
  Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
44
46
  command.option(`--${key} <value>`, CLIProfile.ICLIProfileExample[key], "");
45
47
  });
@@ -47,14 +49,13 @@ const addOverridesToCommand = (command) => {
47
49
  };
48
50
  //computeCLIOverrides returns an object that has a value if any of them have been specified at the command line
49
51
  //this is used as the final override when getting a CLIConfig
50
- const computeCLIOverrides = (command) => {
52
+ const ComputeCLIOverrides = (command) => {
51
53
  let overrides = {};
52
54
  Object.keys(CLIProfile.ICLIProfileExample).forEach((key) => {
53
55
  const source = command.getOptionValueSource(key);
54
- if (source == 'cli') {
56
+ if (source == "cli") {
55
57
  overrides[key] = command.getOptionValue(key);
56
58
  }
57
- return overrides;
58
59
  });
59
60
  return overrides;
60
61
  };
@@ -68,12 +69,12 @@ program.command("none", { hidden: true, isDefault: true })
68
69
  /**
69
70
  * Plan command is responsible for reading files and creating a Coalesce Deployment Plan
70
71
  */
71
- addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
72
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
72
73
  .option("-d, --dir <dir>", "Coalesce pipeline Yaml file path", ".")
73
74
  .option("--out <plan-location>", "Coalesce plan location", "./coa-plan.json")
74
75
  .description("plan a Coalesce deployment")
75
76
  .action((options, cmd) => {
76
- const cliOverrides = computeCLIOverrides(cmd);
77
+ const cliOverrides = ComputeCLIOverrides(cmd);
77
78
  const optsWithGlobals = cmd.optsWithGlobals();
78
79
  const directoryPath = optsWithGlobals.dir;
79
80
  let logContextToUse;
@@ -89,7 +90,7 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
89
90
  Shared.CLIOperations.DisableNonCLIConsoleLogs();
90
91
  }
91
92
  let config;
92
- return CLIProfile.GetCLIConfig(cliOverrides)
93
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
93
94
  .then((configResult) => {
94
95
  config = configResult;
95
96
  return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined);
@@ -118,11 +119,12 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Plan))
118
119
  /**
119
120
  * Deploy command is responsible for taking an already generated plan, and executing it
120
121
  */
121
- addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
122
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
122
123
  .option("-p, --plan <plan-location>", "Coalesce plan location", "./coa-plan.json")
124
+ .option("-o, --out <output json>", "Run Results Output in Json ")
123
125
  .description("run a coalesce deployment plan")
124
126
  .action((options, cmd) => {
125
- const cliOverrides = computeCLIOverrides(cmd);
127
+ const cliOverrides = ComputeCLIOverrides(cmd);
126
128
  const optsWithGlobals = cmd.optsWithGlobals();
127
129
  const plan = JSON.parse(fs_1.default.readFileSync(optsWithGlobals.plan, { encoding: "utf-8" }));
128
130
  // const config = JSON.parse(fs.readFileSync(cmd.config, { encoding: "utf-8" }))
@@ -140,7 +142,7 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
140
142
  let logContextToUse;
141
143
  let runInfo;
142
144
  let config;
143
- return CLIProfile.GetCLIConfig(cliOverrides)
145
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
144
146
  .then((configResult) => {
145
147
  config = configResult;
146
148
  return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined);
@@ -161,14 +163,17 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
161
163
  const { runCounter, runCompletion, logContext } = result;
162
164
  logContextToUse = logContext !== null && logContext !== void 0 ? logContext : {};
163
165
  LogCLI.infoContext(logContextToUse, chalk_1.default.whiteBright(`Job ${runCounter}: ${chalk_1.default.green("running")}...`));
164
- return runCompletion;
166
+ return runCompletion.finally(() => {
167
+ const outputFilePath = optsWithGlobals.out;
168
+ CommonCLI.FinishWithOutputFile(logContextToUse, outputFilePath, runCounter, config.token);
169
+ });
165
170
  })
166
171
  .then(() => {
167
172
  LogCLI.infoContext(logContextToUse, "Deployment successful!");
168
173
  Shared.CLIOperations.ExitCLISafe(0);
169
174
  })
170
175
  .catch(error => {
171
- LogCLI.errorContext(logContextToUse, chalk_1.default.redBright(`An error occurred during deployment ${error}`));
176
+ LogCLI.errorContext(logContextToUse, chalk_1.default.redBright(`An error occurred during deployment ${error.toString()}`));
172
177
  Shared.CLIOperations.ExitCLISafe(1);
173
178
  });
174
179
  });
@@ -176,10 +181,11 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Deploy))
176
181
  /**
177
182
  * Refresh command begins a locally executed Coalesce Environment Run
178
183
  */
179
- addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh))
184
+ AddOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh))
180
185
  .description("runs a Coalesce pipeline")
186
+ .option("-o, --out <output json>", "Run Results Output in Json ")
181
187
  .action((options, command) => {
182
- const cliOverrides = computeCLIOverrides(command);
188
+ const cliOverrides = ComputeCLIOverrides(command);
183
189
  const optsWithGlobals = command.optsWithGlobals();
184
190
  //const token = fs.readFileSync(cmd.token, { encoding: "utf8" })
185
191
  //const config = JSON.parse(fs.readFileSync(cmd.config, { encoding: "utf8" }))
@@ -201,21 +207,26 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh)
201
207
  //WHY DO WE HAVE THIS CONFIG?
202
208
  let runInfo;
203
209
  let config;
204
- return CLIProfile.GetCLIConfig(cliOverrides)
210
+ return CLIProfile.GetCLIConfig(cliOverrides, optsWithGlobals.config)
205
211
  .then((configResult) => {
206
212
  config = configResult;
207
213
  return Shared.SchedulerOperations.AuthenticateFirebaseTokenAndRetrieveTeamInfoForCLI(config.token, undefined);
208
- }).then(({ teamInfo }) => {
214
+ })
215
+ .then(({ teamInfo }) => {
209
216
  Shared.Logging.SetBackendGlobalContext({ userID: teamInfo.fbUserID, orgID: teamInfo.fbTeamID });
210
217
  runInfo = {
211
218
  runType: Shared.Runner.ERunType.refresh,
212
219
  runStatus: Shared.Runner.ERunStatus.running,
213
220
  runDetails: {
214
- environmentID: config.runDetails.environmentID
221
+ environmentID: config.runDetails.environmentID,
222
+ jobID: config.runDetails.jobID,
223
+ includeNodesSelector: config.runDetails.includeNodesSelector,
224
+ excludeNodesSelector: config.runDetails.excludeNodesSelector
215
225
  },
216
226
  userCredentials: config.userCredentials,
217
227
  runTimeParameters: {}
218
228
  };
229
+ Shared.Common.CleanupUndefinedValuesFromObject(runInfo);
219
230
  LogCLIInternal.infoContext(logContextToUse, "cliOverrides", cliOverrides);
220
231
  LogCLIInternal.infoContext(logContextToUse, "got the cli config", config);
221
232
  LogCLIInternal.infoContext(logContextToUse, "got the run info", config);
@@ -225,11 +236,13 @@ addOverridesToCommand(program.command(Shared.CLIOperations.ECLICommands.Refresh)
225
236
  const { runCounter, runCompletion, logContext } = result;
226
237
  logContextToUse = logContext !== null && logContext !== void 0 ? logContext : {};
227
238
  LogCLI.infoContext(logContextToUse, chalk_1.default.whiteBright(`Refresh run initialized. RunCounter: ${runCounter}`));
228
- return runCompletion;
229
- })
230
- .then(() => {
231
- LogCLI.infoContext(logContextToUse, "Refresh successful!");
232
- Shared.CLIOperations.ExitCLISafe(0);
239
+ return runCompletion.finally(() => {
240
+ const outputFilePath = optsWithGlobals.out;
241
+ CommonCLI.FinishWithOutputFile(logContextToUse, outputFilePath, runCounter, config.token);
242
+ }).then(() => {
243
+ LogCLI.infoContext(logContextToUse, "Refresh successful!");
244
+ Shared.CLIOperations.ExitCLISafe(0);
245
+ });
233
246
  })
234
247
  .catch(error => {
235
248
  LogCLI.errorContext(logContextToUse, chalk_1.default.redBright(`Error during refresh!: ${error.toString()}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coalescesoftware/coa",
3
- "version": "1.0.101",
3
+ "version": "1.0.113",
4
4
  "license": "ISC",
5
5
  "author": "Coalesce Automation, Inc.",
6
6
  "main": "index.js",
@@ -12,7 +12,7 @@
12
12
  "start-cli-debug": "yarn run start --debug"
13
13
  },
14
14
  "dependencies": {
15
- "@coalescesoftware/shared": "^1.0.110",
15
+ "@coalescesoftware/shared": "^1.0.113",
16
16
  "chalk": "^4.1.2",
17
17
  "commander": "^9.2.0",
18
18
  "firebase": "8.2.0",